diff --git a/toonz/sources/include/tmetaimage.h b/toonz/sources/include/tmetaimage.h index 9d360c7..5992c4f 100644 --- a/toonz/sources/include/tmetaimage.h +++ b/toonz/sources/include/tmetaimage.h @@ -186,7 +186,7 @@ public: data().touch(); } void dataChanged(const TVariant &value) - { if (m_locks == 0) onDataChanged(value); } + { LockEvents lock(*this); if (m_locks == 1) onDataChanged(value); } void fixData() { LockEvents lock(*this); onFixData(); } }; diff --git a/toonz/sources/include/tools/assistant.h b/toonz/sources/include/tools/assistant.h index f79377a..53b3ac2 100644 --- a/toonz/sources/include/tools/assistant.h +++ b/toonz/sources/include/tools/assistant.h @@ -108,6 +108,7 @@ public: Circle, CircleFill, CircleCross, + CircleDiagonalCross, CircleDots, CircleDoubleDots, }; @@ -211,6 +212,8 @@ protected: const TStringId m_idPoints; const TStringId m_idX; const TStringId m_idY; + const TStringId m_idZ; + const TStringId m_idW; const TStringId m_idMagnetism; TAssistantPointMap m_points; @@ -315,11 +318,11 @@ protected: double getDrawingAlpha(bool enabled = true) const; double getDrawingGridAlpha() const; - void drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize, double alpha) const; - void drawMark(const TPointD &p, const TPointD &normal, double pixelSize, double alpha) const; - void drawDot(const TPointD &p, double alpha) const; - void drawPoint(const TAssistantPoint &point, double pixelSize) const; - void drawIndex(const TPointD &p, int index, bool selected, double pixelSize) const; + static void drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize, double alpha); + static void drawMark(const TPointD &p, const TPointD &normal, double pixelSize, double alpha); + static void drawDot(const TPointD &p, double alpha); + static void drawPoint(const TAssistantPoint &point, double pixelSize); + static void drawIndex(const TPointD &p, int index, bool selected, double pixelSize); inline void drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize) const { drawSegment(p0, p1, pixelSize, getDrawingAlpha()); } diff --git a/toonz/sources/tnztools/CMakeLists.txt b/toonz/sources/tnztools/CMakeLists.txt index 1518eee..b044977 100644 --- a/toonz/sources/tnztools/CMakeLists.txt +++ b/toonz/sources/tnztools/CMakeLists.txt @@ -33,6 +33,8 @@ set(HEADERS stylepickertool.h toonzvectorbrushtool.h vectorselectiontool.h + assistants/assistantline.h + assistants/assistantvanishingpoint.h ../include/tools/RGBpicker.h ../include/tools/cursormanager.h ../include/tools/cursors.h @@ -143,6 +145,7 @@ set(SOURCES assistants/guidelineellipse.cpp assistants/assistantvanishingpoint.cpp assistants/assistantline.cpp + assistants/assistantperspective.cpp assistants/assistantellipse.cpp assistants/replicatoraffine.cpp assistants/replicatorgrid.cpp diff --git a/toonz/sources/tnztools/assistant.cpp b/toonz/sources/tnztools/assistant.cpp index a342f5e..e037f9b 100644 --- a/toonz/sources/tnztools/assistant.cpp +++ b/toonz/sources/tnztools/assistant.cpp @@ -158,6 +158,8 @@ TAssistantBase::TAssistantBase(TMetaObject &object): m_idPoints("points"), m_idX("x"), m_idY("y"), + m_idZ("z"), + m_idW("w"), m_basePoint() { addProperty( new TBoolProperty(m_idEnabled.str(), getEnabled()) ); @@ -433,7 +435,7 @@ TAssistantBase::getDrawingGridAlpha() const //--------------------------------------------------------------------------------------------------- void -TAssistantBase::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize, double alpha) const { +TAssistantBase::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize, double alpha) { double colorBlack[4] = { 0.0, 0.0, 0.0, alpha }; double colorWhite[4] = { 1.0, 1.0, 1.0, alpha }; @@ -458,7 +460,7 @@ TAssistantBase::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSi //--------------------------------------------------------------------------------------------------- void -TAssistantBase::drawMark(const TPointD &p, const TPointD &normal, double pixelSize, double alpha) const { +TAssistantBase::drawMark(const TPointD &p, const TPointD &normal, double pixelSize, double alpha) { TPointD d = normal*5*pixelSize; drawSegment(p - d,p + d, pixelSize, alpha); } @@ -466,7 +468,7 @@ TAssistantBase::drawMark(const TPointD &p, const TPointD &normal, double pixelSi //--------------------------------------------------------------------------------------------------- void -TAssistantBase::drawDot(const TPointD &p, double alpha) const { +TAssistantBase::drawDot(const TPointD &p, double alpha) { double colorBlack[4] = { 0.0, 0.0, 0.0, alpha }; double colorWhite[4] = { 1.0, 1.0, 1.0, alpha }; @@ -491,7 +493,7 @@ TAssistantBase::drawDot(const TPointD &p, double alpha) const { //--------------------------------------------------------------------------------------------------- void -TAssistantBase::drawPoint(const TAssistantPoint &point, double pixelSize) const { +TAssistantBase::drawPoint(const TAssistantPoint &point, double pixelSize) { if (!point.visible) return; double radius = point.radius; @@ -518,26 +520,31 @@ TAssistantBase::drawPoint(const TAssistantPoint &point, double pixelSize) const tglDrawDisk(point.position, radius*pixelSize); } - TPointD crossDx(pixelSize*crossSize, 0.0); - TPointD crossDy(0.0, pixelSize*crossSize); + TPointD crossA(pixelSize*crossSize, 0.0); + TPointD crossB(0.0, pixelSize*crossSize); TPointD gridDx(pixelSize*radius, 0.0); TPointD gridDy(0.0, pixelSize*radius); + bool cross = point.type == TAssistantPoint::CircleCross + || point.type == TAssistantPoint::CircleDiagonalCross; + if (point.type == TAssistantPoint::CircleDiagonalCross) + { crossA.y = crossB.y; crossB.x = crossA.x; } + // back line tglEnableLineSmooth(true, 2.0*width*lineWidthScale); glColor4dv(colorWhite); - if (point.type == TAssistantPoint::CircleCross) { - tglDrawSegment(point.position - crossDx, point.position + crossDx); - tglDrawSegment(point.position - crossDy, point.position + crossDy); + if (cross) { + tglDrawSegment(point.position - crossA, point.position + crossA); + tglDrawSegment(point.position - crossB, point.position + crossB); } tglDrawCircle(point.position, radius*pixelSize); // front line glLineWidth(width * lineWidthScale); glColor4dv(colorBlack); - if (point.type == TAssistantPoint::CircleCross) { - tglDrawSegment(point.position - crossDx, point.position + crossDx); - tglDrawSegment(point.position - crossDy, point.position + crossDy); + if (cross) { + tglDrawSegment(point.position - crossA, point.position + crossA); + tglDrawSegment(point.position - crossB, point.position + crossB); } tglDrawCircle(point.position, radius*pixelSize); @@ -568,7 +575,7 @@ TAssistantBase::drawPoint(const TAssistantPoint &point, double pixelSize) const //--------------------------------------------------------------------------------------------------- void -TAssistantBase::drawIndex(const TPointD &p, int index, bool selected, double pixelSize) const { +TAssistantBase::drawIndex(const TPointD &p, int index, bool selected, double pixelSize) { static const int segments[7][4] = { { 0, 2, 1, 2 }, // A { 1, 1, 1, 2 }, // B + A + diff --git a/toonz/sources/tnztools/assistants/assistantline.cpp b/toonz/sources/tnztools/assistants/assistantline.cpp index f0a1fd6..f078e45 100644 --- a/toonz/sources/tnztools/assistants/assistantline.cpp +++ b/toonz/sources/tnztools/assistants/assistantline.cpp @@ -1,354 +1,356 @@ // TnzTools includes -#include -#include +#include "assistantline.h" -// TnzCore includes -#include - //***************************************************************************************** // TAssistantLine implementation //***************************************************************************************** -class TAssistantLine final : public TAssistant { - Q_DECLARE_TR_FUNCTIONS(TAssistantVanishingPoint) -public: - const TStringId m_idRestricktA; - const TStringId m_idRestricktB; - const TStringId m_idParallel; - const TStringId m_idGrid; - const TStringId m_idPerspective; - -protected: - TAssistantPoint &m_a; - TAssistantPoint &m_b; - TAssistantPoint &m_grid0; - TAssistantPoint &m_grid1; - -public: - TAssistantLine(TMetaObject &object): - TAssistant(object), - m_idRestricktA("restrictA"), - m_idRestricktB("restrictB"), - m_idParallel("parallel"), - m_idGrid("grid"), - m_idPerspective("perspective"), - m_a( addPoint("a", TAssistantPoint::CircleCross) ), - m_b( addPoint("b", TAssistantPoint::Circle, TPointD(100.0, 0.0)) ), - m_grid0( addPoint("grid0", TAssistantPoint::CircleDoubleDots, TPointD( 0.0,-50.0)) ), - m_grid1( addPoint("grid1", TAssistantPoint::CircleDots, TPointD( 25.0,-75.0)) ) - { - addProperty( new TBoolProperty(m_idRestricktA.str(), getRestrictA()) ); - addProperty( new TBoolProperty(m_idRestricktB.str(), getRestrictB()) ); - addProperty( new TBoolProperty(m_idParallel.str(), getParallel()) ); - addProperty( new TBoolProperty(m_idGrid.str(), getGrid()) ); - addProperty( new TBoolProperty(m_idPerspective.str(), getPerspective()) ); - } - - static QString getLocalName() - { return tr("Line"); } - void updateTranslation() const override { - TAssistant::updateTranslation(); - setTranslation(m_idRestricktA, tr("Restrict A")); - setTranslation(m_idRestricktB, tr("Restrict B")); - setTranslation(m_idParallel, tr("Parallel")); - setTranslation(m_idGrid, tr("Grid")); - setTranslation(m_idPerspective, tr("Perspective")); +TAssistantLine::TAssistantLine(TMetaObject &object): + TAssistant(object), + m_idRestricktA("restrictA"), + m_idRestricktB("restrictB"), + m_idParallel("parallel"), + m_idGrid("grid"), + m_idPerspective("perspective"), + m_a( addPoint("a", TAssistantPoint::CircleCross) ), + m_b( addPoint("b", TAssistantPoint::Circle, TPointD(100.0, 0.0)) ), + m_grid0( addPoint("grid0", TAssistantPoint::CircleDoubleDots, TPointD( 0.0,-50.0)) ), + m_grid1( addPoint("grid1", TAssistantPoint::CircleDots, TPointD( 25.0,-75.0)) ) +{ + addProperty( new TBoolProperty(m_idRestricktA.str(), getRestrictA()) ); + addProperty( new TBoolProperty(m_idRestricktB.str(), getRestrictB()) ); + addProperty( new TBoolProperty(m_idParallel.str(), getParallel()) ); + addProperty( new TBoolProperty(m_idGrid.str(), getGrid()) ); + addProperty( new TBoolProperty(m_idPerspective.str(), getPerspective()) ); +} + + +QString TAssistantLine::getLocalName() + { return tr("Line"); } + + +void TAssistantLine::updateTranslation() const { + TAssistant::updateTranslation(); + setTranslation(m_idRestricktA, tr("Restrict A")); + setTranslation(m_idRestricktB, tr("Restrict B")); + setTranslation(m_idParallel, tr("Parallel")); + setTranslation(m_idGrid, tr("Grid")); + setTranslation(m_idPerspective, tr("Perspective")); +} + + +void TAssistantLine::onDataChanged(const TVariant &value) { + TAssistant::onDataChanged(value); + m_grid0.visible = getGrid() + || (getParallel() && (getRestrictA() || getRestrictB())); + m_grid1.visible = getGrid(); +} + + +void TAssistantLine::fixGrid1(const TPointD &previousA, const TPointD &previousB) { + TPointD dx = previousB - previousA; + double l = norm2(dx); + if (l <= TConsts::epsilon*TConsts::epsilon) return; + dx = dx*(1.0/sqrt(l)); + TPointD dy(-dx.y, dx.x); + + TPointD g1 = m_grid1.position - m_grid0.position; + g1 = TPointD(dx*g1, dy*g1); + + dx = m_b.position - m_a.position; + l = norm2(dx); + if (l <= TConsts::epsilon*TConsts::epsilon) return; + dx = dx*(1.0/sqrt(l)); + dy = TPointD(-dx.y, dx.x); + + m_grid1.position = m_grid0.position + dx*g1.x + dy*g1.y; +} + + +void TAssistantLine::onMovePoint(TAssistantPoint &point, const TPointD &position) { + TPointD previousA = m_a.position; + TPointD previousB = m_b.position; + point.position = position; + if (&point != &m_grid1) + fixGrid1(previousA, previousB); +} + + +void TAssistantLine::getGuidelines( + const TPointD &position, + const TAffine &toTool, + TGuidelineList &outGuidelines ) const +{ + bool restrictA = getRestrictA(); + bool restrictB = getRestrictB(); + bool parallel = getParallel(); + bool perspective = getPerspective(); + + TPointD a = toTool*m_a.position; + TPointD b = toTool*m_b.position; + TPointD ab = b - a; + double abLen2 = norm2(ab); + if (abLen2 < TConsts::epsilon*TConsts::epsilon) return; + + if (parallel) { + TPointD abp = rotate90(ab); + TPointD ag = toTool*m_grid0.position - a; + double k = abp*ag; + if (fabs(k) <= TConsts::epsilon) { + if (restrictA || restrictB) return; + a = position; + } else { + k = (abp*(position - a))/k; + a = a + ag*k; + } + if (perspective && (restrictA || restrictB)) + ab = ab*k; + b = a + ab; } - inline bool getRestrictA() const - { return data()[m_idRestricktA].getBool(); } - inline bool getRestrictB() const - { return data()[m_idRestricktB].getBool(); } - inline bool getParallel() const - { return data()[m_idParallel].getBool(); } - inline bool getGrid() const - { return data()[m_idGrid].getBool(); } - inline bool getPerspective() const - { return data()[m_idPerspective].getBool(); } - - void onDataChanged(const TVariant &value) override { - TAssistant::onDataChanged(value); - m_grid0.visible = getGrid() - || (getParallel() && (getRestrictA() || getRestrictB())); - m_grid1.visible = getGrid(); + if (restrictA && restrictB) + outGuidelines.push_back(TGuidelineP( + new TGuidelineLine( + getEnabled(), getMagnetism(), a, b ))); + else if (restrictA) + outGuidelines.push_back(TGuidelineP( + new TGuidelineRay( + getEnabled(), getMagnetism(), a, b ))); + else if (restrictB) + outGuidelines.push_back(TGuidelineP( + new TGuidelineRay( + getEnabled(), getMagnetism(), b, a ))); // b first + else + outGuidelines.push_back(TGuidelineP( + new TGuidelineInfiniteLine( + getEnabled(), getMagnetism(), a, b ))); +} + + +void TAssistantLine::drawRuler( + const TPointD &a, + const TPointD &b, + const TPointD &grid0, + const TPointD &grid1, + const TPointD *perspectiveBase, + double alpha ) +{ + double pixelSize = sqrt(tglGetPixelSize2()); + double minStep = 10.0*pixelSize; + + TPointD direction = b - a; + double l2 = norm2(direction); + if (l2 <= TConsts::epsilon*TConsts::epsilon) return; + double dirLen = sqrt(l2); + TPointD dirProj = direction*(1.0/l2); + TPointD normal = TPointD(-direction.y, direction.x)*(1.0/dirLen); + + double xg0 = dirProj*(grid0 - a); + double xg1 = dirProj*(grid1 - a); + + if (perspectiveBase) { + // draw perspective + double xa0 = dirProj*(*perspectiveBase - a); + double k = 0.0, begin = 0.0, end = 0.0; + if (!calcPerspectiveStep(minStep/dirLen, 0.0, 1.0, xa0, xg0, xg1, k, begin, end)) return; + for(double x = begin; fabs(x) < fabs(end); x *= k) + drawMark(a + direction*(xa0 + x), normal, pixelSize, alpha); + } else { + // draw linear + double dx = fabs(xg1 - xg0); + if (dx*dirLen < minStep) return; + for(double x = xg0 - floor(xg0/dx)*dx; x < 1.0; x += dx) + drawMark(a + direction*x, normal, pixelSize, alpha); } - -private: - void fixGrid1(const TPointD &previousA, const TPointD &previousB) { - TPointD dx = previousB - previousA; - double l = norm2(dx); - if (l <= TConsts::epsilon*TConsts::epsilon) return; - dx = dx*(1.0/sqrt(l)); - TPointD dy(-dx.y, dx.x); - - TPointD g1 = m_grid1.position - m_grid0.position; - g1 = TPointD(dx*g1, dy*g1); - - dx = m_b.position - m_a.position; - l = norm2(dx); - if (l <= TConsts::epsilon*TConsts::epsilon) return; - dx = dx*(1.0/sqrt(l)); - dy = TPointD(-dx.y, dx.x); - - m_grid1.position = m_grid0.position + dx*g1.x + dy*g1.y; +} + + +void TAssistantLine::drawLine( + const TAffine &matrix, + const TAffine &matrixInv, + double pixelSize, + const TPointD &a, + const TPointD &b, + bool restrictA, + bool restrictB, + double alpha ) +{ + const TRectD oneBox(-1.0, -1.0, 1.0, 1.0); + TPointD aa = matrix*a; + TPointD bb = matrix*b; + if ( restrictA && restrictB ? TGuidelineLineBase::truncateLine(oneBox, aa, bb) + : restrictA ? TGuidelineLineBase::truncateRay (oneBox, aa, bb) + : restrictB ? TGuidelineLineBase::truncateRay (oneBox, bb, aa) // aa first + : TGuidelineLineBase::truncateInfiniteLine(oneBox, aa, bb) ) + drawSegment(matrixInv*aa, matrixInv*bb, pixelSize, alpha); +} + + +void TAssistantLine::drawGrid( + const TPointD &a, + const TPointD &b, + const TPointD &grid0, + const TPointD &grid1, + bool restrictA, + bool restrictB, + bool perspective, + double alpha ) +{ + TAffine4 modelview, projection; + glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a); + glGetDoublev(GL_PROJECTION_MATRIX, projection.a); + TAffine matrix = (projection*modelview).get2d(); + TAffine matrixInv = matrix.inv(); + double pixelSize = sqrt(tglGetPixelSize2()); + double minStep = (perspective ? 2.5 : 10.0)*pixelSize; + + TPointD ab = b - a; + double abLen2 = norm2(ab); + if (abLen2 < TConsts::epsilon*TConsts::epsilon) return; + double abLen = sqrt(abLen2); + + TPointD abp = rotate90(ab); + TPointD ag = grid0 - a; + if (fabs(abp*ag) <= TConsts::epsilon) { + if (restrictA || restrictB) return; + ag = abp; } - -public: - void onMovePoint(TAssistantPoint &point, const TPointD &position) override { - TPointD previousA = m_a.position; - TPointD previousB = m_b.position; - point.position = position; - if (&point != &m_grid1) - fixGrid1(previousA, previousB); + double agLen2 = norm2(ag); + if (agLen2 < TConsts::epsilon*TConsts::epsilon) return; + double abpAgK = 1.0/(abp*ag); + TPointD abpAgProj = abp*abpAgK; + + // draw restriction lines + if (perspective) { + if (restrictA) drawLine(matrix, matrixInv, pixelSize, a, a + ag, false, false, alpha); + if (restrictB) drawLine(matrix, matrixInv, pixelSize, a, a + ag + ab, false, false, alpha); + } else { + if (restrictA) drawLine(matrix, matrixInv, pixelSize, a, a + ag, false, false, alpha); + if (restrictB) drawLine(matrix, matrixInv, pixelSize, b, b + ag, false, false, alpha); } - void getGuidelines( - const TPointD &position, - const TAffine &toTool, - TGuidelineList &outGuidelines ) const override - { - bool restrictA = getRestrictA(); - bool restrictB = getRestrictB(); - bool parallel = getParallel(); - bool perspective = getPerspective(); - - TPointD a = toTool*m_a.position; - TPointD b = toTool*m_b.position; - TPointD ab = b - a; - double abLen2 = norm2(ab); - if (abLen2 < TConsts::epsilon*TConsts::epsilon) return; - - if (parallel) { - TPointD abp = rotate90(ab); - TPointD ag = toTool*m_grid0.position - a; - double k = abp*ag; - if (fabs(k) <= TConsts::epsilon) { - if (restrictA || restrictB) return; - a = position; - } else { - k = (abp*(position - a))/k; - a = a + ag*k; - } - if (perspective && (restrictA || restrictB)) - ab = ab*k; - b = a + ab; - } - - if (restrictA && restrictB) - outGuidelines.push_back(TGuidelineP( - new TGuidelineLine( - getEnabled(), getMagnetism(), a, b ))); - else if (restrictA) - outGuidelines.push_back(TGuidelineP( - new TGuidelineRay( - getEnabled(), getMagnetism(), a, b ))); - else if (restrictB) - outGuidelines.push_back(TGuidelineP( - new TGuidelineRay( - getEnabled(), getMagnetism(), b, a ))); // b first - else - outGuidelines.push_back(TGuidelineP( - new TGuidelineInfiniteLine( - getEnabled(), getMagnetism(), a, b ))); + double minStepX = fabs(minStep*abLen*abpAgK); + if (minStepX <= TConsts::epsilon) return; + + // calculate bounds + const TRectD oneBox(-1.0, -1.0, 1.0, 1.0); + TPointD corners[4] = { + TPointD(oneBox.x0, oneBox.y0), + TPointD(oneBox.x0, oneBox.y1), + TPointD(oneBox.x1, oneBox.y0), + TPointD(oneBox.x1, oneBox.y1) }; + double minX = 0.0, maxX = 0.0; + for(int i = 0; i < 4; ++i) { + double x = abpAgProj * (matrixInv*corners[i] - a); + if (i == 0 || x < minX) minX = x; + if (i == 0 || x > maxX) maxX = x; } - -private: - void drawRuler(const TPointD &a, const TPointD &b, double pixelSize, bool perspective) const { - double minStep = 10.0*pixelSize; - double alpha = getDrawingAlpha(); - - TPointD direction = b - a; - double l2 = norm2(direction); - if (l2 <= TConsts::epsilon*TConsts::epsilon) return; - double dirLen = sqrt(l2); - TPointD dirProj = direction*(1.0/l2); - TPointD normal = TPointD(-direction.y, direction.x)*(1.0/dirLen); - - double xg0 = dirProj*(m_grid0.position - a); - double xg1 = dirProj*(m_grid1.position - a); - - if (perspective) { - // draw perspective - double xa0 = dirProj*(m_a.position - a); - double k = 0.0, begin = 0.0, end = 0.0; - if (!calcPerspectiveStep(minStep/dirLen, 0.0, 1.0, xa0, xg0, xg1, k, begin, end)) return; - for(double x = begin; fabs(x) < fabs(end); x *= k) - drawMark(a + direction*(xa0 + x), normal, pixelSize, alpha); - } else { - // draw linear - double dx = fabs(xg1 - xg0); - if (dx*dirLen < minStep) return; - for(double x = xg0 - floor(xg0/dx)*dx; x < 1.0; x += dx) - drawMark(a + direction*x, normal, pixelSize, alpha); + if (maxX <= minX) return; + + double x0 = abpAgProj*(grid0 - a); + double x1 = abpAgProj*(grid1 - a); + + if (perspective) { + double k = 0.0, begin = 0.0, end = 0.0; + if (!calcPerspectiveStep(minStepX, minX, maxX, 0.0, x0, x1, k, begin, end)) return; + double abk = 1.0/fabs(x0); + for(double x = begin; fabs(x) < fabs(end); x *= k) { + TPointD ca = a + ag*x; + TPointD cb = ca + ab*(abk*x); + drawLine(matrix, matrixInv, pixelSize, ca, cb, restrictA, restrictB, alpha); + } + } else { + double dx = fabs(x1 - x0); + if (dx < minStepX) return; + for(double x = x0 + ceil((minX - x0)/dx)*dx; x < maxX; x += dx) { + TPointD ca = a + ag*x; + drawLine(matrix, matrixInv, pixelSize, ca, ca + ab, restrictA, restrictB, alpha); } } - - void drawLine( - const TAffine &matrix, - const TAffine &matrixInv, - double pixelSize, - const TPointD &a, - const TPointD &b, - bool restrictA, - bool restrictB, - double alpha ) const - { - const TRectD oneBox(-1.0, -1.0, 1.0, 1.0); - TPointD aa = matrix*a; - TPointD bb = matrix*b; - if ( restrictA && restrictB ? TGuidelineLineBase::truncateLine(oneBox, aa, bb) - : restrictA ? TGuidelineLineBase::truncateRay (oneBox, aa, bb) - : restrictB ? TGuidelineLineBase::truncateRay (oneBox, bb, aa) // aa first - : TGuidelineLineBase::truncateInfiniteLine(oneBox, aa, bb) ) - drawSegment(matrixInv*aa, matrixInv*bb, pixelSize, alpha); +} + + +void TAssistantLine::draw(TToolViewer*, bool enabled) const { + double alpha = getDrawingAlpha(enabled); + bool restrictA = getRestrictA(); + bool restrictB = getRestrictB(); + bool parallel = getParallel(); + bool grid = getGrid(); + bool perspective = getPerspective(); + + // common data about viewport + const TRectD oneBox(-1.0, -1.0, 1.0, 1.0); + TAffine4 modelview, projection; + glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a); + glGetDoublev(GL_PROJECTION_MATRIX, projection.a); + TAffine matrix = (projection*modelview).get2d(); + TAffine matrixInv = matrix.inv(); + double pixelSize = sqrt(tglGetPixelSize2()); + + // calculate range + TPointD aa = matrix*m_a.position; + TPointD bb = matrix*m_b.position; + bool success = false; + if (restrictA && restrictB) + success = TGuidelineLineBase::truncateLine(oneBox, aa, bb); + else if (restrictA) + success = TGuidelineLineBase::truncateRay(oneBox, aa, bb); + else if (restrictB) + success = TGuidelineLineBase::truncateRay(oneBox, bb, aa); + else + success = TGuidelineLineBase::truncateInfiniteLine(oneBox, aa, bb); + + if (!success) { + // line is out of screen, bud grid still can be visible + if (grid && getParallel()) + drawGrid( + m_a.position, + m_b.position, + m_grid0.position, + m_grid1.position, + restrictA, + restrictB, + perspective, + getDrawingGridAlpha() ); + return; } - - void drawGrid( - const TAffine &matrix, - const TAffine &matrixInv, - double pixelSize, - bool restrictA, - bool restrictB, - bool perspective ) const - { - double minStep = 10.0*pixelSize; - - double alpha = getDrawingGridAlpha(); - TPointD a = m_a.position; - TPointD b = m_b.position; - TPointD ab = b - a; - double abLen2 = norm2(ab); - if (abLen2 < TConsts::epsilon*TConsts::epsilon) return; - double abLen = sqrt(abLen2); - - TPointD g0 = m_grid0.position; - TPointD g1 = m_grid1.position; - - TPointD abp = rotate90(ab); - TPointD ag = g0 - a; - if (fabs(abp*ag) <= TConsts::epsilon) { - if (restrictA || restrictB) return; - ag = abp; - } - double agLen2 = norm2(ag); - if (agLen2 < TConsts::epsilon*TConsts::epsilon) return; - double agLen = sqrt(agLen2); - double abpAgK = 1.0/(abp*ag); - TPointD abpAgProj = abp*abpAgK; - - // draw restriction lines - if (perspective) { - if (restrictA) drawLine(matrix, matrixInv, pixelSize, a, a + ag, false, false, alpha); - if (restrictB) drawLine(matrix, matrixInv, pixelSize, a, a + ag + ab, false, false, alpha); + + TPointD a = matrixInv*aa; + TPointD b = matrixInv*bb; + + // draw line + drawSegment(a, b, pixelSize, alpha); + + // draw restriction marks + if (restrictA || (!parallel && grid && perspective)) + drawDot(m_a.position); + if (restrictB) + drawDot(m_b.position); + + if (grid) { + if (getParallel()) { + drawGrid( + m_a.position, + m_b.position, + m_grid0.position, + m_grid1.position, + restrictA, + restrictB, + perspective, + getDrawingGridAlpha() ); } else { - if (restrictA) drawLine(matrix, matrixInv, pixelSize, a, a + ag, false, false, alpha); - if (restrictB) drawLine(matrix, matrixInv, pixelSize, b, b + ag, false, false, alpha); - } - - double minStepX = fabs(minStep*abLen*abpAgK); - if (minStepX <= TConsts::epsilon) return; - - // calculate bounds - const TRectD oneBox(-1.0, -1.0, 1.0, 1.0); - TPointD corners[4] = { - TPointD(oneBox.x0, oneBox.y0), - TPointD(oneBox.x0, oneBox.y1), - TPointD(oneBox.x1, oneBox.y0), - TPointD(oneBox.x1, oneBox.y1) }; - double minX = 0.0, maxX = 0.0; - for(int i = 0; i < 4; ++i) { - double x = abpAgProj * (matrixInv*corners[i] - a); - if (i == 0 || x < minX) minX = x; - if (i == 0 || x > maxX) maxX = x; - } - if (maxX <= minX) return; - - double x0 = abpAgProj*(g0 - a); - double x1 = abpAgProj*(g1 - a); - - if (perspective) { - double k = 0.0, begin = 0.0, end = 0.0; - if (!calcPerspectiveStep(minStepX, minX, maxX, 0.0, x0, x1, k, begin, end)) return; - double abk = 1.0/fabs(x0); - for(double x = begin; fabs(x) < fabs(end); x *= k) { - TPointD ca = a + ag*x; - TPointD cb = ca + ab*(abk*x); - drawLine(matrix, matrixInv, pixelSize, ca, cb, restrictA, restrictB, alpha); - } - } else { - double dx = fabs(x1 - x0); - if (dx < minStepX) return; - for(double x = x0 + ceil((minX - x0)/dx)*dx; x < maxX; x += dx) { - TPointD ca = a + ag*x; - drawLine(matrix, matrixInv, pixelSize, ca, ca + ab, restrictA, restrictB, alpha); - } + drawRuler( + a, b, m_grid0.position, m_grid1.position, + perspective ? &m_a.position : nullptr, getDrawingAlpha() ); } } +} -public: - void draw(TToolViewer *viewer, bool enabled) const override { - double alpha = getDrawingAlpha(enabled); - bool restrictA = getRestrictA(); - bool restrictB = getRestrictB(); - bool parallel = getParallel(); - bool grid = getGrid(); - bool perspective = getPerspective(); - - // common data about viewport - const TRectD oneBox(-1.0, -1.0, 1.0, 1.0); - TAffine4 modelview, projection; - glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a); - glGetDoublev(GL_PROJECTION_MATRIX, projection.a); - TAffine matrix = (projection*modelview).get2d(); - TAffine matrixInv = matrix.inv(); - double pixelSize = sqrt(tglGetPixelSize2()); - - // calculate range - TPointD aa = matrix*m_a.position; - TPointD bb = matrix*m_b.position; - bool success = false; - if (restrictA && restrictB) - success = TGuidelineLineBase::truncateLine(oneBox, aa, bb); - else if (restrictA) - success = TGuidelineLineBase::truncateRay(oneBox, aa, bb); - else if (restrictB) - success = TGuidelineLineBase::truncateRay(oneBox, bb, aa); - else - success = TGuidelineLineBase::truncateInfiniteLine(oneBox, aa, bb); - - if (!success) { - // line is out of screen, bud grid still can be visible - if (grid && getParallel()) - drawGrid(matrix, matrixInv, pixelSize, restrictA, restrictB, perspective); - return; - } - - TPointD a = matrixInv*aa; - TPointD b = matrixInv*bb; - - // draw line - drawSegment(a, b, pixelSize, alpha); - - // draw restriction marks - if (restrictA || (!parallel && grid && perspective)) - drawDot(m_a.position); - if (restrictB) - drawDot(m_b.position); - - if (grid) { - if (getParallel()) { - drawGrid(matrix, matrixInv, pixelSize, restrictA, restrictB, perspective); - } else { - drawRuler(a, b, pixelSize, perspective); - } - } - } -}; //***************************************************************************************** diff --git a/toonz/sources/tnztools/assistants/assistantline.h b/toonz/sources/tnztools/assistants/assistantline.h new file mode 100644 index 0000000..5069906 --- /dev/null +++ b/toonz/sources/tnztools/assistants/assistantline.h @@ -0,0 +1,98 @@ +#pragma once + +#ifndef ASSISTANTLINE_INCLUDED +#define ASSISTANTLINE_INCLUDED + + +// TnzTools includes +#include +#include + + +// TnzCore includes +#include + + +//***************************************************************************************** +// TAssistantLine definition +//***************************************************************************************** + +class TAssistantLine final : public TAssistant { + Q_DECLARE_TR_FUNCTIONS(TAssistantVanishingPoint) +public: + const TStringId m_idRestricktA; + const TStringId m_idRestricktB; + const TStringId m_idParallel; + const TStringId m_idGrid; + const TStringId m_idPerspective; + +protected: + TAssistantPoint &m_a; + TAssistantPoint &m_b; + TAssistantPoint &m_grid0; + TAssistantPoint &m_grid1; + +public: + TAssistantLine(TMetaObject &object); + + static QString getLocalName(); + + void updateTranslation() const override; + + inline bool getRestrictA() const + { return data()[m_idRestricktA].getBool(); } + inline bool getRestrictB() const + { return data()[m_idRestricktB].getBool(); } + inline bool getParallel() const + { return data()[m_idParallel].getBool(); } + inline bool getGrid() const + { return data()[m_idGrid].getBool(); } + inline bool getPerspective() const + { return data()[m_idPerspective].getBool(); } + + void onDataChanged(const TVariant &value) override; + +private: + void fixGrid1(const TPointD &previousA, const TPointD &previousB); + +public: + void onMovePoint(TAssistantPoint &point, const TPointD &position) override; + + void getGuidelines( + const TPointD &position, + const TAffine &toTool, + TGuidelineList &outGuidelines ) const override; + + static void drawRuler( + const TPointD &a, + const TPointD &b, + const TPointD &grid0, + const TPointD &grid1, + const TPointD *perspectiveBase, + double alpha ); + + static void drawLine( + const TAffine &matrix, + const TAffine &matrixInv, + double pixelSize, + const TPointD &a, + const TPointD &b, + bool restrictA, + bool restrictB, + double alpha ); + + static void drawGrid( + const TPointD &a, + const TPointD &b, + const TPointD &grid0, + const TPointD &grid1, + bool restrictA, + bool restrictB, + bool perspective, + double alpha ); + + void draw(TToolViewer *viewer, bool enabled) const override; +}; + + +#endif diff --git a/toonz/sources/tnztools/assistants/assistantperspective.cpp b/toonz/sources/tnztools/assistants/assistantperspective.cpp new file mode 100644 index 0000000..6030dc6 --- /dev/null +++ b/toonz/sources/tnztools/assistants/assistantperspective.cpp @@ -0,0 +1,441 @@ + + +// TnzTools includes +#include +#include + +#include "assistantline.h" +#include "assistantvanishingpoint.h" + +// TnzCore includes +#include + + +//***************************************************************************************** +// TAssistantPerspective implementation +//***************************************************************************************** + +class TAssistantPerspective final : public TAssistant { + Q_DECLARE_TR_FUNCTIONS(TAssistantPerspective) +public: + const TStringId m_idParallelX; + const TStringId m_idParallelY; + const TStringId m_idParallelZ; + const TStringId m_idGridXY; + const TStringId m_idGridYZ; + const TStringId m_idGridZX; + +protected: + TAssistantPoint &m_o; + TAssistantPoint &m_x; + TAssistantPoint &m_y; + TAssistantPoint &m_z; + TAssistantPoint &m_xy; + TAssistantPoint &m_yz; + TAssistantPoint &m_zx; + TAssistantPoint &m_vx; + TAssistantPoint &m_vy; + TAssistantPoint &m_vz; + +public: + TAssistantPerspective(TMetaObject &object): + TAssistant(object), + m_idParallelX("parallelX"), + m_idParallelY("parallelY"), + m_idParallelZ("parallelZ"), + m_idGridXY("gridXY"), + m_idGridYZ("gridYZ"), + m_idGridZX("gridZX"), + m_o ( addPoint("o", TAssistantPoint::CircleCross) ), + m_x ( addPoint("x", TAssistantPoint::CircleFill, TPointD( 50, 0 )) ), + m_y ( addPoint("y", TAssistantPoint::CircleFill, TPointD( 0, 50 )) ), + m_z ( addPoint("z", TAssistantPoint::CircleFill, TPointD( 25, -25 )) ), + m_xy ( addPoint("xy", TAssistantPoint::Circle, TPointD( 50, 50 )) ), + m_yz ( addPoint("yz", TAssistantPoint::Circle, TPointD( 25, 25 )) ), + m_zx ( addPoint("zx", TAssistantPoint::Circle, TPointD( 75, -25 )) ), + m_vx ( addPoint("vx", TAssistantPoint::Circle) ), + m_vy ( addPoint("vy", TAssistantPoint::Circle) ), + m_vz ( addPoint("vz", TAssistantPoint::Circle) ) + { + addProperty( new TBoolProperty(m_idParallelX.str(), getParallelX()) ); + addProperty( new TBoolProperty(m_idParallelY.str(), getParallelY()) ); + addProperty( new TBoolProperty(m_idParallelZ.str(), getParallelZ()) ); + addProperty( new TBoolProperty(m_idGridXY.str(), getGridXY()) ); + addProperty( new TBoolProperty(m_idGridYZ.str(), getGridYZ()) ); + addProperty( new TBoolProperty(m_idGridZX.str(), getGridZX()) ); + } + + + static QString getLocalName() + { return tr("Perspective"); } + + + void updateTranslation() const override { + TAssistant::updateTranslation(); + setTranslation(m_idParallelX, tr("Parallel X")); + setTranslation(m_idParallelY, tr("Parallel Y")); + setTranslation(m_idParallelZ, tr("Parallel Z")); + setTranslation(m_idGridXY, tr("Grid XY")); + setTranslation(m_idGridYZ, tr("Grid YZ")); + setTranslation(m_idGridZX, tr("Grid ZX")); + } + + + inline bool getParallelX() const + { return data()[m_idParallelX].getBool(); } + inline bool getParallelY() const + { return data()[m_idParallelY].getBool(); } + inline bool getParallelZ() const + { return data()[m_idParallelZ].getBool(); } + inline bool getGridXY() const + { return data()[m_idGridXY].getBool(); } + inline bool getGridYZ() const + { return data()[m_idGridYZ].getBool(); } + inline bool getGridZX() const + { return data()[m_idGridZX].getBool(); } + + void onDataChanged(const TVariant &value) override { + TAssistant::onDataChanged(value); + m_xy.visible = !getParallelX() || !getParallelY(); + m_yz.visible = !getParallelY() || !getParallelZ(); + m_zx.visible = !getParallelZ() || !getParallelX(); + fixPoints(); + } + + +private: + void fixAxisPoint( + TPointD &a, + const TAssistantPoint &v, + const TPointD &oldV ) const + { + const TPointD &o = m_o.position; + if (!v.visible) + { a = o + v.position; return; } + + TPointD dv = v.position - o; + TPointD oldDv = oldV - o; + double l = norm2(oldDv); + double ln = norm2(dv); + if (!(l > TConsts::epsilon) || !(ln > TConsts::epsilon)) + return; + + double d = (a - o)*oldDv; + a = o + dv*(d/l); + } + + + inline void fixAxisPoint( + TAssistantPoint &a, + const TAssistantPoint &v, + const TPointD &oldV ) const + { fixAxisPoint(a.position, v, oldV); } + + + void fixVanishingPoint( + TAssistantPoint &v, + const TPointD &a, + const TPointD &oldA ) const + { + const TPointD &o = m_o.position; + TPointD da = a - o; + if (!v.visible) + { v.position = da; return; } + + TPointD oldDa = oldA - o; + double l = norm2(oldDa); + double ln = norm2(da); + if (!(l > TConsts::epsilon) || !(ln > TConsts::epsilon)) + return; + + double d = (v.position - o)*oldDa; + v.position = o + da*(d/l); + } + + + inline void fixVanishingPoint( + TAssistantPoint &v, + const TAssistantPoint &a, + const TPointD &oldA ) const + { fixVanishingPoint(v, a.position, oldA); } + + + void fixVanishingPoint( + TAssistantPoint &v, + const TPointD &a0, + const TPointD &a1, + const TPointD &b0, + const TPointD &b1 ) const + { + TPointD da = a1 - a0; + TPointD db = b1 - b0; + const TPointD ab = b0 - a0; + double k = db.x*da.y - db.y*da.x; + + if ( (&v == &m_vx && getParallelX()) + || (&v == &m_vy && getParallelY()) + || (&v == &m_vz && getParallelZ()) ) + k = 0; + + if (fabs(k) > TConsts::epsilon) { + double lb = (da.x*ab.y - da.y*ab.x)/k; + v.position.x = lb*db.x + b0.x; + v.position.y = lb*db.y + b0.y; + v.visible = true; + } else { + v.position = da; + v.visible = false; + } + } + + + inline void fixVanishingPoint( + TAssistantPoint &v, + const TAssistantPoint &a0, + const TAssistantPoint &a1, + const TAssistantPoint &b0, + const TAssistantPoint &b1 ) const + { fixVanishingPoint(v, a0.position, a1.position, b0.position, b1.position); } + + + static bool lineCross( + TPointD &p, + const TPointD &a, + const TPointD &b, + const TPointD &da, + const TPointD &db ) + { + double d = da.x*db.y - da.y*db.x; + if (!(fabs(d) > TConsts::epsilon)) + return false; + d = 1/d; + p = TPointD( + (a.y*db.x + b.x*db.y)*da.x - (a.x*da.y + b.y*da.x)*db.x, + (a.y*da.x + b.x*da.y)*db.y - (a.x*db.y + b.y*db.x)*da.y )*d; + return true; + } + + + void fixSidePoint( + TPointD &p, + const TPointD &a, // pass 'a' and 'b' by copy + const TPointD &b, + const TAssistantPoint &va, + const TAssistantPoint &vb ) const + { + + TPointD da = va.visible ? va.position - a : va.position; + TPointD db = vb.visible ? vb.position - b : vb.position; + lineCross(p, a, b, da, db); + } + + + inline void fixSidePoint( + TAssistantPoint &p, + const TAssistantPoint &a, + const TAssistantPoint &b, + const TAssistantPoint &va, + const TAssistantPoint &vb ) const + { fixSidePoint(p.position, a.position, b.position, va, vb); } + + + void fixSidePoints() { + fixSidePoint(m_xy, m_x, m_y, m_vy, m_vx); + fixSidePoint(m_yz, m_y, m_z, m_vz, m_vy); + fixSidePoint(m_zx, m_z, m_x, m_vx, m_vz); + } + + + void addGuideline( + const TPointD &position, + const TAffine &toTool, + const TAssistantPoint &v, + TGuidelineList &outGuidelines ) const + { + if (v.visible) { + TPointD p = toTool * v.position; + if (tdistance2(p, position) > 4*TConsts::epsilon*TConsts::epsilon) + outGuidelines.push_back( + new TGuidelineRay( + getEnabled(), + getMagnetism(), + p, + position )); + } else { + TPointD d = toTool.transformDirection(v.position); + if (norm2(d) > 4*TConsts::epsilon*TConsts::epsilon) + outGuidelines.push_back( + new TGuidelineInfiniteLine( + getEnabled(), + getMagnetism(), + position, + position + d )); + } + } + +public: + void onFixPoints() override { + fixVanishingPoint(m_vx, m_o, m_x, m_y, m_xy); + fixVanishingPoint(m_vy, m_o, m_y, m_x, m_xy); + fixVanishingPoint(m_vz, m_o, m_z, m_x, m_zx); + fixSidePoints(); + } + + void onMovePoint(TAssistantPoint &point, const TPointD &position) override { + if (!point.visible) + return; + + TPointD old = point.position; + point.position = position; + + if (&point == &m_o) { + TPointD d = m_o.position - old; + m_x.position += d; + m_y.position += d; + m_z.position += d; + m_xy.position += d; + m_yz.position += d; + m_zx.position += d; + if (m_vx.visible) m_vx.position += d; + if (m_vy.visible) m_vy.position += d; + if (m_vz.visible) m_vz.position += d; + } else + if (&point == &m_x) { + fixVanishingPoint(m_vx, m_x, old); + fixSidePoints(); + } else + if (&point == &m_y) { + fixVanishingPoint(m_vy, m_y, old); + fixSidePoints(); + } else + if (&point == &m_z) { + fixVanishingPoint(m_vz, m_z, old); + fixSidePoints(); + } else + if (&point == &m_xy) { + fixVanishingPoint(m_vx, m_o, m_x, m_y, m_xy); + fixVanishingPoint(m_vy, m_o, m_y, m_x, m_xy); + fixSidePoints(); + } else + if (&point == &m_yz) { + fixVanishingPoint(m_vy, m_o, m_y, m_z, m_yz); + fixVanishingPoint(m_vz, m_o, m_z, m_y, m_yz); + fixSidePoints(); + } else + if (&point == &m_zx) { + fixVanishingPoint(m_vz, m_o, m_z, m_x, m_zx); + fixVanishingPoint(m_vx, m_o, m_x, m_z, m_zx); + fixSidePoints(); + } else + if (&point == &m_vx) { + fixAxisPoint(m_x, m_vx, old); + fixSidePoints(); + } else + if (&point == &m_vy) { + fixAxisPoint(m_y, m_vy, old); + fixSidePoints(); + } else + if (&point == &m_vz) { + fixAxisPoint(m_z, m_vz, old); + fixSidePoints(); + } + } + + void getGuidelines( + const TPointD &position, + const TAffine &toTool, + TGuidelineList &outGuidelines ) const override + { + addGuideline(position, toTool, m_vx, outGuidelines); + addGuideline(position, toTool, m_vy, outGuidelines); + addGuideline(position, toTool, m_vz, outGuidelines); + } + + void drawGrid( + const TAssistantPoint &vx, + const TAssistantPoint &vy, + const TPointD &y ) const + { + double alpha = getDrawingGridAlpha(); + const TPointD &o = m_o.position; + + if (!vx.visible && !vy.visible) { + TAssistantLine::drawGrid( + o, o + vx.position, o, y, false, false, false, alpha ); + return; + } + + if (!vx.visible) { + TAssistantLine::drawGrid( + vy.position, vy.position + vx.position, o, y, false, false, true, alpha ); + return; + } + + TPointD p = y; + if (vy.visible) { + const TPointD &a = vx.position; + const TPointD &b = o; + const TPointD da = y - a; + const TPointD db = vy.position - vx.position; + lineCross(p, a, b, da, db); + } + + TAssistantVanishingPoint::drawPerspectiveGrid(vx.position, o, p, alpha); + } + + void drawVanishingPoint(const TAssistantPoint &v, double pixelSize, double alpha) const { + if (!v.visible) + return; + const TPointD &p = v.position; + TPointD dx(20.0*pixelSize, 0.0); + TPointD dy(0.0, 10.0*pixelSize); + drawSegment(p-dx-dy, p+dx+dy, pixelSize, alpha); + drawSegment(p-dx+dy, p+dx-dy, pixelSize, alpha); + } + + void draw(TToolViewer*, bool enabled) const override { + double pixelSize = sqrt(tglGetPixelSize2()); + double alpha = getDrawingAlpha(enabled); + drawVanishingPoint(m_vx, pixelSize, alpha); + drawVanishingPoint(m_vy, pixelSize, alpha); + drawVanishingPoint(m_vz, pixelSize, alpha); + if (getGridXY()) { + drawGrid(m_vx, m_vy, m_y.position); + drawGrid(m_vy, m_vx, m_x.position); + } + if (getGridYZ()) { + drawGrid(m_vy, m_vz, m_z.position); + drawGrid(m_vz, m_vy, m_y.position); + } + if (getGridZX()) { + drawGrid(m_vz, m_vx, m_x.position); + drawGrid(m_vx, m_vz, m_z.position); + } + } + + void drawEdit(TToolViewer *viewer) const override { + double pixelSize = sqrt(tglGetPixelSize2()); + TPointD xyz; + fixSidePoint(xyz, m_xy.position, m_zx.position, m_vz, m_vy); + drawSegment(xyz, m_xy.position, pixelSize); + drawSegment(xyz, m_yz.position, pixelSize); + drawSegment(xyz, m_zx.position, pixelSize); + drawSegment(m_xy.position, m_x.position, pixelSize); + drawSegment(m_xy.position, m_y.position, pixelSize); + drawSegment(m_yz.position, m_y.position, pixelSize); + drawSegment(m_yz.position, m_z.position, pixelSize); + drawSegment(m_zx.position, m_z.position, pixelSize); + drawSegment(m_zx.position, m_x.position, pixelSize); + drawSegment(m_o.position, m_x.position, pixelSize); + drawSegment(m_o.position, m_y.position, pixelSize); + drawSegment(m_o.position, m_z.position, pixelSize); + TAssistant::drawEdit(viewer); + } +}; + + +//***************************************************************************************** +// Registration +//***************************************************************************************** + +static TAssistantTypeT assistantPerspective("assistantPerspective"); diff --git a/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp b/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp index 61b0792..ac027d4 100644 --- a/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp +++ b/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp @@ -1,375 +1,371 @@ // TnzTools includes -#include -#include +#include "assistantvanishingpoint.h" -// TnzCore includes -#include //***************************************************************************************** // TAssistantVanishingPoint implementation //***************************************************************************************** -class TAssistantVanishingPoint final : public TAssistant { - Q_DECLARE_TR_FUNCTIONS(TAssistantVanishingPoint) -public: - const TStringId m_idPassThrough; - const TStringId m_idGrid; - const TStringId m_idPerspective; - -protected: - TAssistantPoint &m_center; - TAssistantPoint &m_a0; - TAssistantPoint &m_a1; - TAssistantPoint &m_b0; - TAssistantPoint &m_b1; - TAssistantPoint &m_grid0; - TAssistantPoint &m_grid1; - -public: - TAssistantVanishingPoint(TMetaObject &object): - TAssistant(object), - m_idPassThrough("passThrough"), - m_idGrid("grid"), - m_idPerspective("perspective"), - m_center( addPoint("center", TAssistantPoint::CircleCross) ), - m_a0 ( addPoint("a0", TAssistantPoint::Circle, TPointD(-50.0, 0.0)) ), - m_a1 ( addPoint("a1", TAssistantPoint::Circle, TPointD(-75.0, 0.0)) ), - m_b0 ( addPoint("b0", TAssistantPoint::Circle, TPointD( 50.0, 0.0)) ), - m_b1 ( addPoint("b1", TAssistantPoint::Circle, TPointD( 75.0, 0.0)) ), - m_grid0 ( addPoint("grid0", TAssistantPoint::CircleDoubleDots, TPointD( 0.0,-50.0)) ), - m_grid1 ( addPoint("grid1", TAssistantPoint::CircleDots, TPointD( 25.0,-50.0)) ) - { - addProperty( new TBoolProperty(m_idPassThrough.str(), getPassThrough()) ); - addProperty( new TBoolProperty(m_idGrid.str(), getGrid()) ); - addProperty( new TBoolProperty(m_idPerspective.str(), getPerspective()) ); - } - static QString getLocalName() +TAssistantVanishingPoint::TAssistantVanishingPoint(TMetaObject &object): + TAssistant(object), + m_idPassThrough("passThrough"), + m_idGrid("grid"), + m_idPerspective("perspective"), + m_center( addPoint("center", TAssistantPoint::CircleCross) ), + m_a0 ( addPoint("a0", TAssistantPoint::Circle, TPointD(-50.0, 0.0)) ), + m_a1 ( addPoint("a1", TAssistantPoint::Circle, TPointD(-75.0, 0.0)) ), + m_b0 ( addPoint("b0", TAssistantPoint::Circle, TPointD( 50.0, 0.0)) ), + m_b1 ( addPoint("b1", TAssistantPoint::Circle, TPointD( 75.0, 0.0)) ), + m_grid0 ( addPoint("grid0", TAssistantPoint::CircleDoubleDots, TPointD( 0.0,-50.0)) ), + m_grid1 ( addPoint("grid1", TAssistantPoint::CircleDots, TPointD( 25.0,-50.0)) ) +{ + addProperty( new TBoolProperty(m_idPassThrough.str(), getPassThrough()) ); + addProperty( new TBoolProperty(m_idGrid.str(), getGrid()) ); + addProperty( new TBoolProperty(m_idPerspective.str(), getPerspective()) ); +} + + +QString TAssistantVanishingPoint::getLocalName() { return tr("Vanishing Point"); } - void updateTranslation() const override { - TAssistant::updateTranslation(); - setTranslation(m_idPassThrough, tr("Pass Through")); - setTranslation(m_idGrid, tr("Grid")); - setTranslation(m_idPerspective, tr("Perspective")); - } - inline bool getPassThrough() const - { return data()[m_idPassThrough].getBool(); } - inline bool getGrid() const - { return data()[m_idGrid].getBool(); } - inline bool getPerspective() const - { return data()[m_idPerspective].getBool(); } +void TAssistantVanishingPoint::updateTranslation() const { + TAssistant::updateTranslation(); + setTranslation(m_idPassThrough, tr("Pass Through")); + setTranslation(m_idGrid, tr("Grid")); + setTranslation(m_idPerspective, tr("Perspective")); +} - void onDataChanged(const TVariant &value) override { - TAssistant::onDataChanged(value); - m_grid0.visible = m_grid1.visible = getGrid(); - } -private: - void fixCenter() { - if ( !(m_a0.position == m_a1.position) - && !(m_b0.position == m_b1.position) ) - { - const TPointD &a = m_a0.position; - const TPointD &b = m_b0.position; - const TPointD da = m_a1.position - a; - const TPointD db = m_b1.position - b; - const TPointD ab = b - a; - double k = db.x*da.y - db.y*da.x; - if (fabs(k) > TConsts::epsilon) { - double lb = (da.x*ab.y - da.y*ab.x)/k; - m_center.position.x = lb*db.x + b.x; - m_center.position.y = lb*db.y + b.y; - } +void TAssistantVanishingPoint::onDataChanged(const TVariant &value) { + TAssistant::onDataChanged(value); + m_grid0.visible = m_grid1.visible = getGrid(); +} + + +void TAssistantVanishingPoint::fixCenter() { + if ( !(m_a0.position == m_a1.position) + && !(m_b0.position == m_b1.position) ) + { + const TPointD &a = m_a0.position; + const TPointD &b = m_b0.position; + const TPointD da = m_a1.position - a; + const TPointD db = m_b1.position - b; + const TPointD ab = b - a; + double k = db.x*da.y - db.y*da.x; + if (fabs(k) > TConsts::epsilon) { + double lb = (da.x*ab.y - da.y*ab.x)/k; + m_center.position.x = lb*db.x + b.x; + m_center.position.y = lb*db.y + b.y; } } +} - void fixSidePoint(TAssistantPoint &p0, TAssistantPoint &p1, TPointD previousP0) { - if (p0.position != m_center.position && p0.position != p1.position) { - TPointD dp0 = p0.position - m_center.position; - TPointD dp1 = p1.position - previousP0; - double l0 = norm(dp0); - double l1 = norm(dp1); - if (l0 > TConsts::epsilon && l0 + l1 > TConsts::epsilon) - p1.position = m_center.position + dp0*((l0 + l1)/l0); - } + +void TAssistantVanishingPoint::fixSidePoint(TAssistantPoint &p0, TAssistantPoint &p1, TPointD previousP0) { + if (p0.position != m_center.position && p0.position != p1.position) { + TPointD dp0 = p0.position - m_center.position; + TPointD dp1 = p1.position - previousP0; + double l0 = norm(dp0); + double l1 = norm(dp1); + if (l0 > TConsts::epsilon && l0 + l1 > TConsts::epsilon) + p1.position = m_center.position + dp0*((l0 + l1)/l0); } +} - void fixSidePoint(TAssistantPoint &p0, TAssistantPoint &p1) - { fixSidePoint(p0, p1, p0.position); } - void fixGrid1(const TPointD &previousCenter, const TPointD &previousGrid0) { - TPointD dx = previousCenter - previousGrid0; - double l = norm2(dx); - if (l <= TConsts::epsilon*TConsts::epsilon) return; - dx = dx*(1.0/sqrt(l)); - TPointD dy(-dx.y, dx.x); +void TAssistantVanishingPoint::fixSidePoint(TAssistantPoint &p0, TAssistantPoint &p1) + { fixSidePoint(p0, p1, p0.position); } - TPointD d = m_grid1.position - previousGrid0; - double x = (dx*d); - double y = (dy*d); - dx = m_center.position - m_grid0.position; - l = norm2(dx); - if (l <= TConsts::epsilon*TConsts::epsilon) return; - dx = dx*(1.0/sqrt(l)); - dy = TPointD(-dx.y, dx.x); +void TAssistantVanishingPoint::fixGrid1(const TPointD &previousCenter, const TPointD &previousGrid0) { + TPointD dx = previousCenter - previousGrid0; + double l = norm2(dx); + if (l <= TConsts::epsilon*TConsts::epsilon) return; + dx = dx*(1.0/sqrt(l)); + TPointD dy(-dx.y, dx.x); - m_grid1.position = m_grid0.position + dx*x + dy*y; - } + TPointD d = m_grid1.position - previousGrid0; + double x = (dx*d); + double y = (dy*d); + + dx = m_center.position - m_grid0.position; + l = norm2(dx); + if (l <= TConsts::epsilon*TConsts::epsilon) return; + dx = dx*(1.0/sqrt(l)); + dy = TPointD(-dx.y, dx.x); -public: - void onFixPoints() override { + m_grid1.position = m_grid0.position + dx*x + dy*y; +} + + +void TAssistantVanishingPoint::onFixPoints() { + fixSidePoint(m_a0, m_a1); + fixSidePoint(m_b0, m_b1); + fixCenter(); +} + + +void TAssistantVanishingPoint::onMovePoint(TAssistantPoint &point, const TPointD &position) { + TPointD previousCenter = m_center.position; + TPointD previous = point.position; + point.position = position; + if (&point == &m_center) { fixSidePoint(m_a0, m_a1); fixSidePoint(m_b0, m_b1); + } else + if (&point == &m_a0) { + fixSidePoint(m_a0, m_a1, previous); + fixSidePoint(m_b0, m_b1); + } else + if (&point == &m_b0) { + fixSidePoint(m_a0, m_a1); + fixSidePoint(m_b0, m_b1, previous); + } else + if (&point == &m_a1) { fixCenter(); + fixSidePoint(m_a0, m_a1); + fixSidePoint(m_b0, m_b1); + } else + if (&point == &m_b1) { + fixCenter(); + fixSidePoint(m_b0, m_b1); + fixSidePoint(m_a0, m_a1); } - void onMovePoint(TAssistantPoint &point, const TPointD &position) override { - TPointD previousCenter = m_center.position; - TPointD previous = point.position; - point.position = position; - if (&point == &m_center) { - fixSidePoint(m_a0, m_a1); - fixSidePoint(m_b0, m_b1); - } else - if (&point == &m_a0) { - fixSidePoint(m_a0, m_a1, previous); - fixSidePoint(m_b0, m_b1); - } else - if (&point == &m_b0) { - fixSidePoint(m_a0, m_a1); - fixSidePoint(m_b0, m_b1, previous); - } else - if (&point == &m_a1) { - fixCenter(); - fixSidePoint(m_a0, m_a1); - fixSidePoint(m_b0, m_b1); - } else - if (&point == &m_b1) { - fixCenter(); - fixSidePoint(m_b0, m_b1); - fixSidePoint(m_a0, m_a1); - } - - if (&point == &m_grid0) { - fixGrid1(previousCenter, previous); - } else - if (&point != &m_grid1) { - fixGrid1(previousCenter, m_grid0.position); - } + if (&point == &m_grid0) { + fixGrid1(previousCenter, previous); + } else + if (&point != &m_grid1) { + fixGrid1(previousCenter, m_grid0.position); } - - void getGuidelines( - const TPointD &position, - const TAffine &toTool, - TGuidelineList &outGuidelines ) const override - { - if (getPassThrough()) { - outGuidelines.push_back(TGuidelineP( - new TGuidelineInfiniteLine( - getEnabled(), - getMagnetism(), - toTool * m_center.position, - position ))); - } else { - outGuidelines.push_back(TGuidelineP( - new TGuidelineRay( - getEnabled(), - getMagnetism(), - toTool * m_center.position, - position ))); - } +} + + +void TAssistantVanishingPoint::getGuidelines( + const TPointD &position, + const TAffine &toTool, + TGuidelineList &outGuidelines ) const +{ + if (getPassThrough()) { + outGuidelines.push_back(TGuidelineP( + new TGuidelineInfiniteLine( + getEnabled(), + getMagnetism(), + toTool * m_center.position, + position ))); + } else { + outGuidelines.push_back(TGuidelineP( + new TGuidelineRay( + getEnabled(), + getMagnetism(), + toTool * m_center.position, + position ))); } - - void drawSimpleGrid() const { - double alpha = getDrawingGridAlpha(); - const TPointD &p = m_center.position; - double pixelSize = sqrt(tglGetPixelSize2()); - double minStep = 5.0*pixelSize; - - // calculate rays count and step - TPointD d0 = m_grid0.position - p; - TPointD d1 = m_grid1.position - p; - TPointD dp = d0; - double l = norm(d0); - if (l <= TConsts::epsilon) return; - if (norm2(d1) <= TConsts::epsilon*TConsts::epsilon) return; - double a0 = atan(d0); - double a1 = atan(d1); - double da = fabs(a1 - a0); - if (da > M_PI) da = M_PI - da; - if (da < TConsts::epsilon) da = TConsts::epsilon; - double count = M_2PI/da; - if (count > 1e6) return; - double radiusPart = minStep/(da*l); - if (radiusPart > 1.0) return; - int raysCount = (int)round(count); - double step = M_2PI/(double)raysCount; - - // common data about viewport - const TRectD oneBox(-1.0, -1.0, 1.0, 1.0); - TAffine4 modelview, projection; - glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a); - glGetDoublev(GL_PROJECTION_MATRIX, projection.a); - TAffine matrix = (projection*modelview).get2d(); - TAffine matrixInv = matrix.inv(); - - // calculate range - if (!(matrixInv*oneBox).contains(p)) { - TPointD corners[4] = { - TPointD(oneBox.x0, oneBox.y0), - TPointD(oneBox.x0, oneBox.y1), - TPointD(oneBox.x1, oneBox.y0), - TPointD(oneBox.x1, oneBox.y1) }; - double angles[4]; - double a0 = 0.0, a1 = 0.0, da = 0.0; - for(int i = 0; i < 4; ++i) { - angles[i] = atan(matrixInv*corners[i] - p) + M_2PI; - for(int j = 0; j < i; ++j) { - double d = fabs(angles[i] - angles[j]); - if (d > M_PI) d = M_2PI - d; - if (d > da) da = d, a0 = angles[i], a1 = angles[j]; - } +} + + +void TAssistantVanishingPoint::drawSimpleGrid( + const TPointD ¢er, + const TPointD &grid0, + const TPointD &grid1, + double alpha ) +{ + double pixelSize = sqrt(tglGetPixelSize2()); + double minStep = 5.0*pixelSize; + + // calculate rays count and step + TPointD d0 = grid0 - center; + TPointD d1 = grid1 - center; + TPointD dp = d0; + double l = norm(d0); + if (l <= TConsts::epsilon) return; + if (norm2(d1) <= TConsts::epsilon*TConsts::epsilon) return; + double a0 = atan(d0); + double a1 = atan(d1); + double da = fabs(a1 - a0); + if (da > M_PI) da = M_PI - da; + if (da < TConsts::epsilon) da = TConsts::epsilon; + double count = M_2PI/da; + if (count > 1e6) return; + double radiusPart = minStep/(da*l); + if (radiusPart > 1.0) return; + int raysCount = (int)round(count); + double step = M_2PI/(double)raysCount; + + // common data about viewport + const TRectD oneBox(-1.0, -1.0, 1.0, 1.0); + TAffine4 modelview, projection; + glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a); + glGetDoublev(GL_PROJECTION_MATRIX, projection.a); + TAffine matrix = (projection*modelview).get2d(); + TAffine matrixInv = matrix.inv(); + + // calculate range + if (!(matrixInv*oneBox).contains(center)) { + TPointD corners[4] = { + TPointD(oneBox.x0, oneBox.y0), + TPointD(oneBox.x0, oneBox.y1), + TPointD(oneBox.x1, oneBox.y0), + TPointD(oneBox.x1, oneBox.y1) }; + double angles[4]; + double a0 = 0.0, a1 = 0.0, da = 0.0; + for(int i = 0; i < 4; ++i) { + angles[i] = atan(matrixInv*corners[i] - center) + M_2PI; + for(int j = 0; j < i; ++j) { + double d = fabs(angles[i] - angles[j]); + if (d > M_PI) d = M_2PI - d; + if (d > da) da = d, a0 = angles[i], a1 = angles[j]; } - if (a1 < a0) std::swap(a1, a0); - if (a1 - a0 > M_PI) { std::swap(a1, a0); a1 += M_2PI; } - double a = atan(dp) + M_2PI; - a0 = ceil ((a0 - a)/step)*step + a; - a1 = floor((a1 - a)/step)*step + a; - - double s = sin(a0 - a); - double c = cos(a0 - a); - dp = TPointD(c*dp.x - s*dp.y, s*dp.x + c*dp.y); - raysCount = (int)round((a1 - a0)/step); - } - - // draw rays - double s = sin(step); - double c = cos(step); - for(int i = 0; i < raysCount; ++i) { - TPointD p0 = matrix*(p + dp*radiusPart); - TPointD p1 = matrix*(p + dp); - if (TGuidelineLineBase::truncateRay(oneBox, p0, p1)) - drawSegment(matrixInv*p0, matrixInv*p1, pixelSize, alpha); - dp = TPointD(c*dp.x - s*dp.y, s*dp.x + c*dp.y); } + if (a1 < a0) std::swap(a1, a0); + if (a1 - a0 > M_PI) { std::swap(a1, a0); a1 += M_2PI; } + double a = atan(dp) + M_2PI; + a0 = ceil ((a0 - a)/step)*step + a; + a1 = floor((a1 - a)/step)*step + a; + + double s = sin(a0 - a); + double c = cos(a0 - a); + dp = TPointD(c*dp.x - s*dp.y, s*dp.x + c*dp.y); + raysCount = (int)round((a1 - a0)/step); } - void drawPerspectiveGrid() const { - // initial calculations - double alpha = getDrawingGridAlpha(); - const TPointD ¢er = m_center.position; - double pixelSize = sqrt(tglGetPixelSize2()); - double minStep = 5.0*pixelSize; - - TPointD step = m_grid1.position - m_grid0.position; - double stepLen2 = norm2(step); - double stepLen = sqrt(stepLen2); - if (stepLen <= minStep) return; - TPointD stepProj = step*(1.0/stepLen2); - - TPointD dp = center - m_grid0.position; - double startX = dp*stepProj; - TPointD zeroPoint = m_grid0.position + step*startX; - TPointD cz = zeroPoint - center; - double czLen2 = norm2(cz); - double czLen = sqrt(czLen2); - if (czLen <= TConsts::epsilon) return; - TPointD zeroProj = cz*(1.0/czLen2); - - double smallK = minStep/stepLen; - TPointD smallGrid0 = center - dp*smallK; - TPointD smallStep = step*smallK; - TPointD smallStepProj = stepProj*(1/smallK); - - // common data about viewport - const TRectD oneBox(-1.0, -1.0, 1.0, 1.0); - TAffine4 modelview, projection; - glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a); - glGetDoublev(GL_PROJECTION_MATRIX, projection.a); - TAffine matrix = (projection*modelview).get2d(); - TAffine matrixInv = matrix.inv(); - - // calculate bounds - bool found = false; - double minx = 0.0, maxx = 0.0; - TPointD p0 = matrix*(smallGrid0); - TPointD p1 = matrix*(smallGrid0 + smallStep); - if (TGuidelineLineBase::truncateInfiniteLine(oneBox, p0, p1)) { - p0 = matrixInv*p0; - p1 = matrixInv*p1; - minx = (p0 - smallGrid0)*smallStepProj; - maxx = (p1 - smallGrid0)*smallStepProj; - if (maxx < minx) std::swap(maxx, minx); + // draw rays + double s = sin(step); + double c = cos(step); + for(int i = 0; i < raysCount; ++i) { + TPointD p0 = matrix*(center + dp*radiusPart); + TPointD p1 = matrix*(center + dp); + if (TGuidelineLineBase::truncateRay(oneBox, p0, p1)) + drawSegment(matrixInv*p0, matrixInv*p1, pixelSize, alpha); + dp = TPointD(c*dp.x - s*dp.y, s*dp.x + c*dp.y); + } +} + + +void TAssistantVanishingPoint::drawPerspectiveGrid( + const TPointD ¢er, + const TPointD &grid0, + const TPointD &grid1, + double alpha ) +{ + // initial calculations + double pixelSize = sqrt(tglGetPixelSize2()); + double minStep = 5.0*pixelSize; + + TPointD step = grid1 - grid0; + double stepLen2 = norm2(step); + double stepLen = sqrt(stepLen2); + if (stepLen <= minStep) return; + TPointD stepProj = step*(1.0/stepLen2); + + TPointD dp = center - grid0; + double startX = dp*stepProj; + TPointD zeroPoint = grid0 + step*startX; + TPointD cz = zeroPoint - center; + double czLen2 = norm2(cz); + double czLen = sqrt(czLen2); + if (czLen <= TConsts::epsilon) return; + TPointD zeroProj = cz*(1.0/czLen2); + + double smallK = minStep/stepLen; + TPointD smallGrid0 = center - dp*smallK; + TPointD smallStep = step*smallK; + TPointD smallStepProj = stepProj*(1/smallK); + + // common data about viewport + const TRectD oneBox(-1.0, -1.0, 1.0, 1.0); + TAffine4 modelview, projection; + glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a); + glGetDoublev(GL_PROJECTION_MATRIX, projection.a); + TAffine matrix = (projection*modelview).get2d(); + TAffine matrixInv = matrix.inv(); + + // calculate bounds + bool found = false; + double minx = 0.0, maxx = 0.0; + TPointD p0 = matrix*(smallGrid0); + TPointD p1 = matrix*(smallGrid0 + smallStep); + if (TGuidelineLineBase::truncateInfiniteLine(oneBox, p0, p1)) { + p0 = matrixInv*p0; + p1 = matrixInv*p1; + minx = (p0 - smallGrid0)*smallStepProj; + maxx = (p1 - smallGrid0)*smallStepProj; + if (maxx < minx) std::swap(maxx, minx); + found = true; + } + if (!oneBox.contains(matrix*center)) { + TPointD corners[4] = { + TPointD(oneBox.x0, oneBox.y0), + TPointD(oneBox.x0, oneBox.y1), + TPointD(oneBox.x1, oneBox.y0), + TPointD(oneBox.x1, oneBox.y1) }; + for(int i = 0; i < 4; ++i) { + TPointD p = matrixInv*corners[i] - center; + double k = p*zeroProj; + if (k < TConsts::epsilon) continue; + double x = startX + (p*stepProj)/k; + if (!found || x < minx) minx = x; + if (!found || x > maxx) maxx = x; found = true; } - if (!oneBox.contains(matrix*center)) { - TPointD corners[4] = { - TPointD(oneBox.x0, oneBox.y0), - TPointD(oneBox.x0, oneBox.y1), - TPointD(oneBox.x1, oneBox.y0), - TPointD(oneBox.x1, oneBox.y1) }; - for(int i = 0; i < 4; ++i) { - TPointD p = matrixInv*corners[i] - center; - double k = p*zeroProj; - if (k < TConsts::epsilon) continue; - double x = startX + (p*stepProj)/k; - if (!found || x < minx) minx = x; - if (!found || x > maxx) maxx = x; - found = true; - } - if (maxx <= minx) return; - } - - // draw grid - if (maxx - minx > 1e6) return; - for(double x = ceil(minx); x < maxx; ++x) { - TPointD p = smallGrid0 + smallStep*x - center; - TPointD p0 = matrix*(center + p); - TPointD p1 = matrix*(center + p*2.0); - if (TGuidelineLineBase::truncateRay(oneBox, p0, p1)) - drawSegment(matrixInv*p0, matrixInv*p1, pixelSize, alpha); - } + if (maxx <= minx) return; + } - // draw horizon - p0 = matrix*(center); - p1 = matrix*(center + step); - if (TGuidelineLineBase::truncateInfiniteLine(oneBox, p0, p1)) + // draw grid + if (maxx - minx > 1e6) return; + for(double x = ceil(minx); x < maxx; ++x) { + TPointD p = smallGrid0 + smallStep*x - center; + TPointD p0 = matrix*(center + p); + TPointD p1 = matrix*(center + p*2.0); + if (TGuidelineLineBase::truncateRay(oneBox, p0, p1)) drawSegment(matrixInv*p0, matrixInv*p1, pixelSize, alpha); } - void draw(TToolViewer *viewer, bool enabled) const override { - double pixelSize = sqrt(tglGetPixelSize2()); - const TPointD &p = m_center.position; - TPointD dx(20.0*pixelSize, 0.0); - TPointD dy(0.0, 10.0*pixelSize); - double alpha = getDrawingAlpha(enabled); - drawSegment(p-dx-dy, p+dx+dy, pixelSize, alpha); - drawSegment(p-dx+dy, p+dx-dy, pixelSize, alpha); - if (getGrid()) { - if (getPerspective()) - drawPerspectiveGrid(); - else - drawSimpleGrid(); - } + // draw horizon + p0 = matrix*(center); + p1 = matrix*(center + step); + if (TGuidelineLineBase::truncateInfiniteLine(oneBox, p0, p1)) + drawSegment(matrixInv*p0, matrixInv*p1, pixelSize, alpha); +} + + +void TAssistantVanishingPoint::draw(TToolViewer*, bool enabled) const { + double pixelSize = sqrt(tglGetPixelSize2()); + const TPointD &p = m_center.position; + TPointD dx(20.0*pixelSize, 0.0); + TPointD dy(0.0, 10.0*pixelSize); + double alpha = getDrawingAlpha(enabled); + drawSegment(p-dx-dy, p+dx+dy, pixelSize, alpha); + drawSegment(p-dx+dy, p+dx-dy, pixelSize, alpha); + if (getGrid()) { + const TPointD &p0 = m_grid0.position; + const TPointD &p1 = m_grid1.position; + double gridAlpha = getDrawingGridAlpha(); + if (getPerspective()) + drawPerspectiveGrid(p, p0, p1, gridAlpha); + else + drawSimpleGrid(p, p0, p1, gridAlpha); } +} + + +void TAssistantVanishingPoint::drawEdit(TToolViewer *viewer) const { + double pixelSize = sqrt(tglGetPixelSize2()); + drawSegment(m_center.position, m_a1.position, pixelSize); + drawSegment(m_center.position, m_b1.position, pixelSize); + TAssistant::drawEdit(viewer); +} - void drawEdit(TToolViewer *viewer) const override { - double pixelSize = sqrt(tglGetPixelSize2()); - drawSegment(m_center.position, m_a1.position, pixelSize); - drawSegment(m_center.position, m_b1.position, pixelSize); - TAssistant::drawEdit(viewer); - } -}; //***************************************************************************************** // Registration //***************************************************************************************** + static TAssistantTypeT assistantVanishingPoint("assistantVanishingPoint"); diff --git a/toonz/sources/tnztools/assistants/assistantvanishingpoint.h b/toonz/sources/tnztools/assistants/assistantvanishingpoint.h new file mode 100644 index 0000000..b7b276c --- /dev/null +++ b/toonz/sources/tnztools/assistants/assistantvanishingpoint.h @@ -0,0 +1,83 @@ +#pragma once + +#ifndef ASSISTANTVANISHINGPOINT_INCLUDED +#define ASSISTANTVANISHINGPOINT_INCLUDED + + +// TnzTools includes +#include +#include + +// TnzCore includes +#include + + +//***************************************************************************************** +// TAssistantVanishingPoint definition +//***************************************************************************************** + +class TAssistantVanishingPoint final : public TAssistant { + Q_DECLARE_TR_FUNCTIONS(TAssistantVanishingPoint) +public: + const TStringId m_idPassThrough; + const TStringId m_idGrid; + const TStringId m_idPerspective; + +protected: + TAssistantPoint &m_center; + TAssistantPoint &m_a0; + TAssistantPoint &m_a1; + TAssistantPoint &m_b0; + TAssistantPoint &m_b1; + TAssistantPoint &m_grid0; + TAssistantPoint &m_grid1; + +public: + TAssistantVanishingPoint(TMetaObject &object); + + static QString getLocalName(); + + void updateTranslation() const override; + + inline bool getPassThrough() const + { return data()[m_idPassThrough].getBool(); } + inline bool getGrid() const + { return data()[m_idGrid].getBool(); } + inline bool getPerspective() const + { return data()[m_idPerspective].getBool(); } + + void onDataChanged(const TVariant &value) override; + +private: + void fixCenter(); + void fixSidePoint(TAssistantPoint &p0, TAssistantPoint &p1, TPointD previousP0); + void fixSidePoint(TAssistantPoint &p0, TAssistantPoint &p1); + void fixGrid1(const TPointD &previousCenter, const TPointD &previousGrid0); + +public: + void onFixPoints() override; + void onMovePoint(TAssistantPoint &point, const TPointD &position) override; + + void getGuidelines( + const TPointD &position, + const TAffine &toTool, + TGuidelineList &outGuidelines ) const override; + + static void drawSimpleGrid( + const TPointD ¢er, + const TPointD &grid0, + const TPointD &grid1, + double alpha ); + + static void drawPerspectiveGrid( + const TPointD ¢er, + const TPointD &grid0, + const TPointD &grid1, + double alpha ); + + void draw(TToolViewer *viewer, bool enabled) const override; + void drawEdit(TToolViewer *viewer) const override; +}; + + +#endif diff --git a/toonz/sources/tnztools/editassistantstool.cpp b/toonz/sources/tnztools/editassistantstool.cpp index 2c98f9e..0a9186a 100644 --- a/toonz/sources/tnztools/editassistantstool.cpp +++ b/toonz/sources/tnztools/editassistantstool.cpp @@ -806,7 +806,7 @@ public: TAssistant::scanAssistants( this, // tool &position, 1, // pointer positions - nullptr, // out guidelines + &m_currentGuidelines, // out guidelines true, // draw false, // enabled only false, // mark enabled