diff --git a/toonz/sources/include/tools/inputmanager.h b/toonz/sources/include/tools/inputmanager.h index 63d3560..5cbe005 100644 --- a/toonz/sources/include/tools/inputmanager.h +++ b/toonz/sources/include/tools/inputmanager.h @@ -1,3 +1,5 @@ +#pragma once + #ifndef INPUTMANAGER_INCLUDED #define INPUTMANAGER_INCLUDED @@ -153,7 +155,7 @@ public: virtual void modifyTrack( const TTrackP &track, const TInputSavePoint::Holder &savePoint, - TTrackList &outTracks ) { } + TTrackList &outTracks ); virtual void modifyTracks( const TTrackList &tracks, const TInputSavePoint::Holder &savePoint, @@ -161,7 +163,7 @@ public: virtual void modifyHover( const TPointD &hover, - THoverList &outHovers ) { } + THoverList &outHovers ); virtual void modifyHovers( const THoverList &hovers, THoverList &outHovers ); diff --git a/toonz/sources/include/tools/modifiertest.h b/toonz/sources/include/tools/modifiertest.h new file mode 100644 index 0000000..b328e0f --- /dev/null +++ b/toonz/sources/include/tools/modifiertest.h @@ -0,0 +1,61 @@ +#pragma once + +#ifndef MODIFIERTEST_INCLUDED +#define MODIFIERTEST_INCLUDED + +// TnzTools includes +#include <tools/inputmanager.h> + +// std includes +#include <cmath> + + +#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 + + +//=================================================================== + +//***************************************************************************************** +// TModifierTest definition +//***************************************************************************************** + +class TModifierTest: public TInputModifier { +public: + class Handler: public TTrackHandler { + public: + std::vector<double> angles; + Handler(TTrack &original): TTrackHandler(original) { } + }; + + class Modifier: public TTrackModifier { + public: + double angle; + double radius; + double speed; + + Modifier(TTrackHandler &handler, double angle, double radius, double speed = 0.25); + TTrackPoint calcPoint(double originalIndex); + }; + +public: + int count; + double radius; + + explicit TModifierTest(); + + void modifyTrack( + const TTrackP &track, + const TInputSavePoint::Holder &savePoint, + TTrackList &outTracks ) override; +}; + + +#endif diff --git a/toonz/sources/include/tools/track.h b/toonz/sources/include/tools/track.h index 2883a19..0efccce 100644 --- a/toonz/sources/include/tools/track.h +++ b/toonz/sources/include/tools/track.h @@ -181,12 +181,10 @@ public: inline int ceilIndex(double index) const { return clampIndex(ceilIndexNoClamp(index)); } - int floorIndex(double index, double &outFrac) const; + int floorIndex(double index, double *outFrac) const; - inline const TTrackPoint& floorPoint(double index, double &outFrac) const + inline const TTrackPoint& floorPoint(double index, double *outFrac = NULL) const { return point(floorIndex(index, outFrac)); } - inline const TTrackPoint& floorPoint(double index) const - { return point(floorIndex(index)); } inline const TTrackPoint& ceilPoint(double index) const { return point(ceilIndex(index)); } @@ -256,19 +254,19 @@ public: inline double originalIndexByIndex(double index) const { double frac; - const TTrackPoint &p0 = floorPoint(index, frac); + const TTrackPoint &p0 = floorPoint(index, &frac); const TTrackPoint &p1 = ceilPoint(index); return interpolationLinear(p0.originalIndex, p1.originalIndex, frac); } inline double timeByIndex(double index) const { double frac; - const TTrackPoint &p0 = floorPoint(index, frac); + const TTrackPoint &p0 = floorPoint(index, &frac); const TTrackPoint &p1 = ceilPoint(index); return interpolationLinear(p0.time, p1.time, frac); } inline double lengthByIndex(double index) const { double frac; - const TTrackPoint &p0 = floorPoint(index, frac); + const TTrackPoint &p0 = floorPoint(index, &frac); const TTrackPoint &p1 = ceilPoint(index); return interpolationLinear(p0.length, p1.length, frac); } @@ -280,7 +278,7 @@ public: inline TTrackPoint interpolateLinear(double index) const { double frac; - const TTrackPoint &p0 = floorPoint(index, frac); + const TTrackPoint &p0 = floorPoint(index, &frac); const TTrackPoint &p1 = ceilPoint(index); return interpolationLinear(p0, p1, frac); } diff --git a/toonz/sources/tnztools/CMakeLists.txt b/toonz/sources/tnztools/CMakeLists.txt index 113061e..c426de8 100644 --- a/toonz/sources/tnztools/CMakeLists.txt +++ b/toonz/sources/tnztools/CMakeLists.txt @@ -48,6 +48,7 @@ set(HEADERS ../include/tools/inputstate.h ../include/tools/track.h ../include/tools/inputmanager.h + ../include/tools/modifiertest.h ) set(SOURCES @@ -115,6 +116,7 @@ set(SOURCES inputstate.cpp track.cpp inputmanager.cpp + modifiertest.cpp ) set(RESOURCES tnztools.qrc) diff --git a/toonz/sources/tnztools/inputmanager.cpp b/toonz/sources/tnztools/inputmanager.cpp index 13069a7..61f7b2a 100644 --- a/toonz/sources/tnztools/inputmanager.cpp +++ b/toonz/sources/tnztools/inputmanager.cpp @@ -23,6 +23,49 @@ TInputModifier::setManager(TInputManager *manager) { void +TInputModifier::modifyTrack( + const TTrackP &track, + const TInputSavePoint::Holder &savePoint, + TTrackList &outTracks ) +{ + if (!track->handler) { + track->handler = new TTrackHandler(*track); + track->handler->tracks.push_back( + new TTrack( + new TTrackModifier(*track->handler) )); + } + + outTracks.insert( + outTracks.end(), + track->handler->tracks.begin(), + track->handler->tracks.end() ); + if (!track->changed()) + return; + + int start = track->size() - track->pointsAdded; + if (start < 0) start = 0; + + for(TTrackList::const_iterator ti = track->handler->tracks.begin(); ti != track->handler->tracks.end(); ++ti) { + TTrack &subTrack = **ti; + + // remove points + if (start < track->size()) { + subTrack.pointsRemoved += subTrack.size() - start; + subTrack.truncate(start); + } + + // add points + for(int i = start; i < track->size(); ++i) + subTrack.push_back( subTrack.modifier->calcPoint(i) ); + subTrack.pointsAdded += subTrack.size() - start; + } + + track->pointsRemoved = 0; + track->pointsAdded = 0; +} + + +void TInputModifier::modifyTracks( const TTrackList &tracks, const TInputSavePoint::Holder &savePoint, @@ -34,6 +77,15 @@ TInputModifier::modifyTracks( void +TInputModifier::modifyHover( + const TPointD &hover, + THoverList &outHovers ) +{ + outHovers.push_back(hover); +} + + +void TInputModifier::modifyHovers( const THoverList &hovers, THoverList &outHovers ) diff --git a/toonz/sources/tnztools/modifiertest.cpp b/toonz/sources/tnztools/modifiertest.cpp new file mode 100644 index 0000000..c74cf17 --- /dev/null +++ b/toonz/sources/tnztools/modifiertest.cpp @@ -0,0 +1,157 @@ + + +#include <tools/modifiertest.h> + + +//***************************************************************************************** +// TModifierTest::Modifier implementation +//***************************************************************************************** + + +TModifierTest::Modifier::Modifier( + TTrackHandler &handler, + double angle, + double radius, + double speed +): + TTrackModifier(handler), + angle(angle), + radius(radius), + speed(speed) +{ } + + +TTrackPoint +TModifierTest::Modifier::calcPoint(double originalIndex) { + TTrackPoint p = TTrackModifier::calcPoint(originalIndex); + + if (p.length > 2.0) { + double frac; + int i0 = original.floorIndex(originalIndex, &frac); + int i1 = original.ceilIndex(originalIndex); + if (i0 < 0) return p; + + if (Handler *handler = dynamic_cast<Handler*>(&this->handler)) { + double angle = this->angle + speed*TTrack::interpolationLinear( + handler->angles[i0], handler->angles[i1], frac); + double radius = 2.0*this->radius*p.pressure; + double s = sin(angle); + double c = cos(angle); + + TPointD tangent = TPointD(1.0, 0.0); // original.calcTangent(originalIndex, fabs(2.0*this->radius/speed)); + p.position.x += radius*(c*tangent.x - s*tangent.y); + p.position.y += radius*(s*tangent.x + c*tangent.y); + p.pressure *= 0.5*(1.0 + c); + } + } else { + p.pressure = 0.0; + } + + return p; +} + + +//***************************************************************************************** +// TModifierTest implementation +//***************************************************************************************** + + +TModifierTest::TModifierTest(): + count(1), + radius(40.0) +{ } + + +void +TModifierTest::modifyTrack( + const TTrackP &track, + const TInputSavePoint::Holder &savePoint, + TTrackList &outTracks ) +{ + const double segmentSize = M_PI/180.0*10.0; + + if (!track->handler) { + if (track->getCurrentKeyState().isPressed(TKey(Qt::Key_T))) { + // TModifierTest::Handler for spiro + track->handler = new Handler(*track); + for(int i = 0; i < count; ++i) + track->handler->tracks.push_back( + new TTrack( + new Modifier( + *track->handler, + i*2.0*M_PI/(double)count, + radius, + 2.0 ))); + } + } + + Handler *handler = dynamic_cast<Handler*>(track->handler.getPointer()); + if (!handler) { + TInputModifier::modifyTrack(track, savePoint, outTracks); + return; + } + + outTracks.insert( + outTracks.end(), + track->handler->tracks.begin(), + track->handler->tracks.end() ); + if (!track->changed()) + return; + + int start = track->size() - track->pointsAdded; + if (start < 0) start = 0; + + // remove angles + if (start < (int)handler->angles.size()) + handler->angles.erase( + handler->angles.begin() + start, + handler->angles.end() ); + + // add angles + for(int i = start; i < track->size(); ++i) { + if (i > 0) { + double dl = (*track)[i].length - (*track)[i-1].length; + double da = (*track)[i].pressure > TTrack::epsilon + ? dl/(2.0*radius*(*track)[i].pressure) : 0.0; + handler->angles.push_back(handler->angles[i-1] + da); + } else { + handler->angles.push_back(0.0); + } + } + + // process sub-tracks + for(TTrackList::const_iterator ti = handler->tracks.begin(); ti != handler->tracks.end(); ++ti) { + TTrack &subTrack = **ti; + + // remove points + int subStart = subTrack.floorIndex(subTrack.indexByOriginalIndex(start)); + if (subStart < 0) subStart = 0; + if (subStart < subTrack.size() && subTrack[subStart].originalIndex + TTrack::epsilon < start) + ++subStart; + + if (subStart < subTrack.size()) { + subTrack.pointsRemoved += subTrack.size() - subStart; + subTrack.truncate(subStart); + } + + // add points + for(int i = start; i < track->size(); ++i) { + if (i > 0) { + double prevAngle = handler->angles[i-1]; + double nextAngle = handler->angles[i]; + if (fabs(nextAngle - prevAngle) > 1.5*segmentSize) { + double step = segmentSize/fabs(nextAngle - prevAngle); + double end = 1.0 - 0.5*step; + for(double frac = step; frac < end; frac += step) + subTrack.push_back( subTrack.modifier->calcPoint((double)i - 1.0 + frac) ); + } + } + subTrack.push_back( subTrack.modifier->calcPoint(i) ); + } + subTrack.pointsAdded += subTrack.size() - subStart; + } + + track->pointsRemoved = 0; + track->pointsAdded = 0; +} + diff --git a/toonz/sources/tnztools/track.cpp b/toonz/sources/tnztools/track.cpp index 27d8b1e..6193c8a 100644 --- a/toonz/sources/tnztools/track.cpp +++ b/toonz/sources/tnztools/track.cpp @@ -54,6 +54,7 @@ TTrack::TTrack(const TTrackModifierP &modifier): buttonHistory(modifier->original.buttonHistory), hasPressure(modifier->original.hasPressure), hasTilt(modifier->original.hasTilt), + modifier(modifier), pointsRemoved(), pointsAdded() { } @@ -71,13 +72,17 @@ TTrack::level() const { return original() ? original()->level() + 1 : 0; } int -TTrack::floorIndex(double index, double &outFrac) const { +TTrack::floorIndex(double index, double *outFrac) const { int i = (int)floor(index + epsilon); - if (i > size() - 1) - { outFrac = 0.0; return size() - 1; } - if (i < 0) - { outFrac = 0.0; return 0; } - outFrac = std::max(0.0, index - (double)i); + if (i > size() - 1) { + if (outFrac) *outFrac = 0.0; + return size() - 1; + } + if (i < 0) { + if (outFrac) *outFrac = 0.0; + return 0; + } + if (outFrac) *outFrac = std::max(0.0, index - (double)i); return i; }