diff --git a/toonz/sources/include/tools/assistant.h b/toonz/sources/include/tools/assistant.h index 625e66f..34c50e9 100644 --- a/toonz/sources/include/tools/assistant.h +++ b/toonz/sources/include/tools/assistant.h @@ -6,8 +6,6 @@ // TnzTools includes #include <tools/track.h> -// TnzLib includes - // TnzCore includes #include <tsmartpointer.h> #include <tgeometry.h> @@ -49,7 +47,7 @@ typedef std::vector<TAssistantPoint> TAssistantPointList; // TGuideline definition //***************************************************************************************** -class DVAPI TGuideline final : public TSmartObject { +class DVAPI TGuideline : public TSmartObject { public: virtual TTrackPoint transformPoint(const TTrackPoint &point) const { return point; } @@ -58,6 +56,8 @@ public: void draw() const { draw(false); } + void drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize, bool active) const; + double calcTrackWeight(const TTrack &track, const TAffine &toScreen, bool &outLongEnough) const; static TGuidelineP findBest(const TGuidelineList &guidelines, const TTrack &track, const TAffine &toScreen, bool &outLongEnough); }; @@ -87,7 +87,7 @@ public: // TAssistant definition //***************************************************************************************** -class DVAPI TAssistant final : public TMetaObjectHandler { +class DVAPI TAssistant : public TMetaObjectHandler { protected: const TStringId m_idPoints; const TStringId m_idX; @@ -130,6 +130,7 @@ protected: //! save object data to variant virtual void onFixData(); + void drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize) const; void drawPoint(const TAssistantPoint &point, double pixelSize) const; public: diff --git a/toonz/sources/tnztools/CMakeLists.txt b/toonz/sources/tnztools/CMakeLists.txt index b272a75..247f89c 100644 --- a/toonz/sources/tnztools/CMakeLists.txt +++ b/toonz/sources/tnztools/CMakeLists.txt @@ -125,6 +125,8 @@ set(SOURCES modifiers/modifiertangents.cpp modifiers/modifiersegmentation.cpp modifiers/modifierassistants.cpp + assistants/guidelineline.cpp + assistants/assistantvanishingpoint.cpp ) set(RESOURCES tnztools.qrc) diff --git a/toonz/sources/tnztools/assistant.cpp b/toonz/sources/tnztools/assistant.cpp index eda9f1e..e2e5ad7 100644 --- a/toonz/sources/tnztools/assistant.cpp +++ b/toonz/sources/tnztools/assistant.cpp @@ -10,6 +10,30 @@ // TGuideline implementation //************************************************************************ +void +TGuideline::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize, bool active) const { + double colorBlack[4] = { 0.0, 0.0, 0.0, 0.5 }; + double colorWhite[4] = { 1.0, 1.0, 1.0, 0.5 }; + if (!active) colorBlack[3] = (colorWhite[3] *= 0.5); + + glPushAttrib(GL_ALL_ATTRIB_BITS); + tglEnableBlending(); + tglEnableLineSmooth(true, 0.5); + TPointD d = p1 - p0; + double k = norm2(d); + if (k > TConsts::epsilon*TConsts::epsilon) { + double k = 0.5*pixelSize/sqrt(k); + d = TPointD(-k*d.y, k*d.x); + glColor4dv(colorWhite); + tglDrawSegment(p0 - d, p1 - d); + glColor4dv(colorBlack); + tglDrawSegment(p0 + d, p1 + d); + } + glPopAttrib(); +} + +//--------------------------------------------------------------------------------------------------- + double TGuideline::calcTrackWeight(const TTrack &track, const TAffine &toScreen, bool &outLongEnough) const { outLongEnough = false; @@ -165,6 +189,29 @@ TAssistant::onFixData() { //--------------------------------------------------------------------------------------------------- void +TAssistant::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize) const { + double colorBlack[4] = { 0.0, 0.0, 0.0, 0.5 }; + double colorWhite[4] = { 1.0, 1.0, 1.0, 0.5 }; + + glPushAttrib(GL_ALL_ATTRIB_BITS); + tglEnableBlending(); + tglEnableLineSmooth(true, 0.5); + TPointD d = p1 - p0; + double k = norm2(d); + if (k > TConsts::epsilon*TConsts::epsilon) { + double k = 0.5*pixelSize/sqrt(k); + d = TPointD(-k*d.y, k*d.x); + glColor4dv(colorWhite); + tglDrawSegment(p0 - d, p1 - d); + glColor4dv(colorBlack); + tglDrawSegment(p0 + d, p1 + d); + } + glPopAttrib(); +} + +//--------------------------------------------------------------------------------------------------- + +void TAssistant::drawPoint(const TAssistantPoint &point, double pixelSize) const { double radius = 10.0; double crossSize = 1.2*radius; @@ -226,6 +273,7 @@ TAssistant::draw(TToolViewer *viewer) const void TAssistant::drawEdit(TToolViewer *viewer) const { // paint all points + draw(viewer); double pixelSize = sqrt(tglGetPixelSize2()); for(int i = 0; i < pointsCount(); ++i) drawPoint(m_points[i], pixelSize); diff --git a/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp b/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp new file mode 100644 index 0000000..f500427 --- /dev/null +++ b/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp @@ -0,0 +1,41 @@ + + +#include "assistantvanishingpoint.h" +#include "guidelineline.h" + +// TnzCore includes +#include "tgl.h" + + +//***************************************************************************************** +// TAssistantVanishingPoint implementation +//***************************************************************************************** + +TAssistantVanishingPoint::TAssistantVanishingPoint(TMetaObject &object): + TAssistant(object) +{ + m_points.push_back(TAssistantPoint( + TAssistantPoint::CircleCross )); +} + +void +TAssistantVanishingPoint::getGuidelines( + const TPointD &position, + const TAffine &toTool, + TGuidelineList &outGuidelines ) const +{ + outGuidelines.push_back(TGuidelineP( + new TGuidelineInfiniteLine( + toTool*m_points.front().position, + position ))); +} + +void +TAssistantVanishingPoint::draw(TToolViewer *viewer) const { + double pixelSize = sqrt(tglGetPixelSize2()); + const TPointD &p = m_points.front().position; + TPointD dx(20.0*pixelSize, 0.0); + TPointD dy(0.0, 10.0*pixelSize); + drawSegment(p-dx-dy, p+dx+dy, pixelSize); + drawSegment(p-dx+dy, p+dx-dy, pixelSize); +} diff --git a/toonz/sources/tnztools/assistants/assistantvanishingpoint.h b/toonz/sources/tnztools/assistants/assistantvanishingpoint.h new file mode 100644 index 0000000..cbd3568 --- /dev/null +++ b/toonz/sources/tnztools/assistants/assistantvanishingpoint.h @@ -0,0 +1,34 @@ +#pragma once + +#ifndef ASSISTANTVANISHINGPOINT_INCLUDED +#define ASSISTANTVANISHINGPOINT_INCLUDED + +// TnzTools includes +#include <tools/assistant.h> + + +#undef DVAPI +#undef DVVAR +#ifdef TNZTOOLS_EXPORTS +#define DVAPI DV_EXPORT_API +#define DVVAR DV_EXPORT_VAR +#else +#define DVAPI DV_IMPORT_API +#define DVVAR DV_IMPORT_VAR +#endif + + +//=================================================================== + +//***************************************************************************************** +// TAssistantVanishingPoint definition +//***************************************************************************************** + +class DVAPI TAssistantVanishingPoint final : public TAssistant { +public: + TAssistantVanishingPoint(TMetaObject &object); + virtual void getGuidelines(const TPointD &position, const TAffine &toTool, TGuidelineList &outGuidelines) const override; + virtual void draw(TToolViewer *viewer) const override; +}; + +#endif diff --git a/toonz/sources/tnztools/assistants/guidelineline.cpp b/toonz/sources/tnztools/assistants/guidelineline.cpp new file mode 100644 index 0000000..3ca0eea --- /dev/null +++ b/toonz/sources/tnztools/assistants/guidelineline.cpp @@ -0,0 +1,117 @@ + + +#include "guidelineline.h" + +// TnzCore includes +#include "tgl.h" + + +//***************************************************************************************** +// TGuidelineLineBase implementation +//***************************************************************************************** + +TGuidelineLineBase::TGuidelineLineBase(const TPointD &p0, const TPointD &p1): + p0(p0), p1(p1) { } + +TPointD +TGuidelineLineBase::calcDirection(const TPointD &p0, const TPointD &p1) { + TPointD d = p1 - p0; + double k = norm2(d); + return k > TConsts::epsilon ? d*(1.0/k) : TPointD(); +} + +void +TGuidelineLineBase::truncateInfiniteLine(const TRectD &bounds, TPointD &p0, TPointD &p1) { + TPointD d = p0 - p1; + TDimensionD size = bounds.getSize(); + if (fabs(d.x)*bounds.y0 > bounds.x0*fabs(d.y)) { + // horizontal + if (fabs(d.x) < TConsts::epsilon) return; + double k = d.y/d.x; + p1 = TPointD(bounds.x1, p0.y + k*(bounds.x1 - p0.x)); + p0 = TPointD(bounds.x0, p0.y + k*(bounds.x0 - p0.x)); + } else { + // vertical + if (fabs(d.y) < TConsts::epsilon) return; + double k = d.x/d.y; + p1 = TPointD(p0.x + k*(bounds.y1 - p0.y), bounds.y1); + p0 = TPointD(p0.x + k*(bounds.y0 - p0.y), bounds.y0); + } +} + +void +TGuidelineLineBase::drawInliniteLine(const TPointD &p0, const TPointD &p1, bool ray, bool active) const { + TAffine4 modelview; + glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a); + + TAffine matrix = modelview.get2d(); + TPointD pp0 = matrix*p0; + TPointD pp1 = matrix*p1; + truncateInfiniteLine(TRectD(-1.0, -1.0, 1.0, 1.0), pp0, pp1); + + TAffine matrixInv = matrix.inv(); + double pixelSize = norm(TPointD(matrixInv.a11 + matrixInv.a12, matrixInv.a21 + matrixInv.a22)); + drawSegment((ray ? p0 : matrixInv*pp0), matrixInv*pp1, pixelSize, active); +} + + +//***************************************************************************************** +// TGuidelineLine implementation +//***************************************************************************************** + +TGuidelineLine::TGuidelineLine(const TPointD &p0, const TPointD &p1): + TGuidelineLineBase(p0, p1), + dir(calcDirection(p0, p1)), + dist(norm(p1 - p0)) { } + +TTrackPoint +TGuidelineLine::transformPoint(const TTrackPoint &point) const { + TTrackPoint p(point); + p.position = p0 + dir * std::max(0.0, std::min(dist, ((p.position - p0)*dir))); + return p; +} + +void +TGuidelineLine::draw(bool active) const + { drawSegment(p0, p1, sqrt(tglGetPixelSize2()), active); } + + +//***************************************************************************************** +// TGuidelineInfiniteLine implementation +//***************************************************************************************** + +TGuidelineInfiniteLine::TGuidelineInfiniteLine(const TPointD &p0, const TPointD &p1): + TGuidelineLineBase(p0, p1), + dir(calcDirection(p0, p1)) { } + +TTrackPoint +TGuidelineInfiniteLine::transformPoint(const TTrackPoint &point) const { + TTrackPoint p(point); + p.position = p0 + dir * ((p.position - p0)*dir); + return p; +} + +void +TGuidelineInfiniteLine::draw(bool active) const + { drawInliniteLine(p0, p1, false, active); } + + +//***************************************************************************************** +// TGuidelineRay implementation +//***************************************************************************************** + +TGuidelineRay::TGuidelineRay(const TPointD &p0, const TPointD &p1): + TGuidelineLineBase(p0, p1), + dir(calcDirection(p0, p1)) { } + +TTrackPoint +TGuidelineRay::transformPoint(const TTrackPoint &point) const { + TTrackPoint p(point); + p.position = p0 + dir * std::max(0.0, ((p.position - p0)*dir)); + return p; +} + +void +TGuidelineRay::draw(bool active) const + { drawInliniteLine(p0, p1, true, active); } + diff --git a/toonz/sources/tnztools/assistants/guidelineline.h b/toonz/sources/tnztools/assistants/guidelineline.h new file mode 100644 index 0000000..470f953 --- /dev/null +++ b/toonz/sources/tnztools/assistants/guidelineline.h @@ -0,0 +1,89 @@ +#pragma once + +#ifndef GUIDELINELINE_INCLUDED +#define GUIDELINELINE_INCLUDED + +// TnzTools includes +#include <tools/assistant.h> + +#include <tgl.h> + + +#undef DVAPI +#undef DVVAR +#ifdef TNZTOOLS_EXPORTS +#define DVAPI DV_EXPORT_API +#define DVVAR DV_EXPORT_VAR +#else +#define DVAPI DV_IMPORT_API +#define DVVAR DV_IMPORT_VAR +#endif + + +//============================================================== + +//***************************************************************************************** +// TGuidelineLineBase definition +//***************************************************************************************** + +class DVAPI TGuidelineLineBase : public TGuideline { +public: + const TPointD p0; + const TPointD p1; + + TGuidelineLineBase(const TPointD &p0, const TPointD &p1); + void drawInliniteLine(const TPointD &p0, const TPointD &p1, bool ray, bool active) const; + static TPointD calcDirection(const TPointD &p0, const TPointD &p1); + static void truncateInfiniteLine(const TRectD &bounds, TPointD &p0, TPointD &p1); +}; + + +//***************************************************************************************** +// TGuidelineLine definition +//***************************************************************************************** + +class DVAPI TGuidelineLine : public TGuidelineLineBase { +public: + const TPointD p0; + const TPointD p1; + const TPointD dir; + const double dist; + + TGuidelineLine(const TPointD &p0, const TPointD &p1); + TTrackPoint transformPoint(const TTrackPoint &point) const override; + void draw(bool active) const override; +}; + + +//***************************************************************************************** +// TGuidelineInfiniteLine definition +//***************************************************************************************** + +class DVAPI TGuidelineInfiniteLine : public TGuidelineLineBase { +public: + const TPointD p0; + const TPointD p1; + const TPointD dir; + + TGuidelineInfiniteLine(const TPointD &p0, const TPointD &p1); + TTrackPoint transformPoint(const TTrackPoint &point) const override; + void draw(bool active) const override; +}; + + +//***************************************************************************************** +// TGuidelineRay definition +//***************************************************************************************** + +class DVAPI TGuidelineRay : public TGuidelineLineBase { +public: + const TPointD p0; + const TPointD p1; + const TPointD dir; + + TGuidelineRay(const TPointD &p0, const TPointD &p1); + TTrackPoint transformPoint(const TTrackPoint &point) const override; + void draw(bool active) const override; +}; + +#endif