diff --git a/toonz/sources/include/tgeometry.h b/toonz/sources/include/tgeometry.h index f5c9a81..f5887cb 100644 --- a/toonz/sources/include/tgeometry.h +++ b/toonz/sources/include/tgeometry.h @@ -202,6 +202,16 @@ inline TPointD normalize(const TPointD &p) { /*! \relates TPointT +This helper function returns the normalized version of the specified point +or zero if it is not possible +*/ +inline TPointD normalizeOrZero(const TPointD &p) { + double n = norm2(p); + return fabs(n) > TConsts::epsilon*TConsts::epsilon ? p*(1/sqrt(n)) : TPointD(); +} + +/*! +\relates TPointT This helper function converts a TPoint (TPointT) into a TPointD */ inline TPointD convert(const TPoint &p) { return TPointD(p.x, p.y); } diff --git a/toonz/sources/include/tools/modifiers/modifierassistants.h b/toonz/sources/include/tools/modifiers/modifierassistants.h index 0ba8059..a040a8c 100644 --- a/toonz/sources/include/tools/modifiers/modifierassistants.h +++ b/toonz/sources/include/tools/modifiers/modifierassistants.h @@ -26,13 +26,16 @@ class DVAPI TModifierAssistants: public TInputModifier { public: - class DVAPI Modifier: public TTrackModifier { + typedef TSubTrackHandler Handler; + class DVAPI Interpolator: public TTrackInterpolator { public: - bool initialized; + const double magnetism; TGuidelineList guidelines; - - Modifier(TTrackHandler &handler); - TTrackPoint calcPoint(double originalIndex) override; + inline Interpolator(TTrack &track, double magnetism): + TTrackInterpolator(track), + magnetism(magnetism > 0 ? (magnetism < 1 ? magnetism : 1) : 0) + { } + TTrackPoint interpolate(double index) override; }; private: @@ -44,10 +47,10 @@ private: bool enabledOnly ) const; public: - bool drawOnly; + double magnetism; double sensitiveLength; - explicit TModifierAssistants(bool drawOnly = false); + explicit TModifierAssistants(double magnetism = 1); void modifyTrack( const TTrack &track, diff --git a/toonz/sources/include/tools/modifiers/modifierline.h b/toonz/sources/include/tools/modifiers/modifierline.h index 495f711..622e2ae 100644 --- a/toonz/sources/include/tools/modifiers/modifierline.h +++ b/toonz/sources/include/tools/modifiers/modifierline.h @@ -24,17 +24,12 @@ // TModifierLine definition //***************************************************************************************** -class TModifierLine: public TInputModifier { +class DVAPI TModifierLine: public TInputModifier { public: - class Modifier: public TTrackModifier { + class DVAPI Handler: public TSubTrackHandler { public: - explicit Modifier(TTrackHandler &handler): - TTrackModifier(handler), fixAngle(), maxPressure() { } - - bool fixAngle; double maxPressure; - - TTrackPoint calcPoint(double originalIndex) override; + inline Handler(): maxPressure() { } }; void modifyTrack( diff --git a/toonz/sources/include/tools/modifiers/modifiersegmentation.h b/toonz/sources/include/tools/modifiers/modifiersegmentation.h index e706d5c..acfb76b 100644 --- a/toonz/sources/include/tools/modifiers/modifiersegmentation.h +++ b/toonz/sources/include/tools/modifiers/modifiersegmentation.h @@ -25,6 +25,10 @@ //***************************************************************************************** class DVAPI TModifierSegmentation: public TInputModifier { +public: + typedef TSubTrackHandler Handler; + typedef TTrackIntrOrig Interpolator; + private: TPointD m_step; int m_maxLevel; diff --git a/toonz/sources/include/tools/modifiers/modifiersimplify.h b/toonz/sources/include/tools/modifiers/modifiersimplify.h index 6f353b8..155dd4a 100644 --- a/toonz/sources/include/tools/modifiers/modifiersimplify.h +++ b/toonz/sources/include/tools/modifiers/modifiersimplify.h @@ -25,15 +25,14 @@ //***************************************************************************************** class DVAPI TModifierSimplify: public TInputModifier { -private: +public: + typedef TSubTrackHandler Handler; + typedef TTrackIntrOrig Interpolator; + double step; -public: explicit TModifierSimplify(double step = 1.0); - void setStep(double step); - inline double getStep() const { return step; } - void modifyTrack( const TTrack &track, TTrackList &outTracks ) override; diff --git a/toonz/sources/include/tools/modifiers/modifiersmooth.h b/toonz/sources/include/tools/modifiers/modifiersmooth.h index 193db53..e814b73 100644 --- a/toonz/sources/include/tools/modifiers/modifiersmooth.h +++ b/toonz/sources/include/tools/modifiers/modifiersmooth.h @@ -26,23 +26,15 @@ class DVAPI TModifierSmooth: public TInputModifier { public: - class DVAPI Modifier: public TTrackModifier { + class DVAPI Handler: public TSubTrackHandler { public: const int radius; - TTrack *smoothedTrack; - - Modifier(TTrackHandler &handler, int radius); - TTrackPoint calcPoint(double originalIndex) override; + inline explicit Handler(int radius): radius(radius) { } }; -private: - int m_radius; - -public: - explicit TModifierSmooth(int radius = 10); + int radius; - void setRadius(int radius); - int getRadius() const { return m_radius; } + explicit TModifierSmooth(int radius = 10); void modifyTrack( const TTrack &track, diff --git a/toonz/sources/include/tools/modifiers/modifiertangents.h b/toonz/sources/include/tools/modifiers/modifiertangents.h index a7e6232..960564e 100644 --- a/toonz/sources/include/tools/modifiers/modifiertangents.h +++ b/toonz/sources/include/tools/modifiers/modifiertangents.h @@ -26,17 +26,15 @@ class DVAPI TModifierTangents: public TInputModifier { public: - class DVAPI Modifier: public TTrackModifier { + typedef TSubTrackHandler Handler; + class DVAPI Interpolator: public TTrackInterpolator { public: - explicit Modifier(TTrackHandler &handler): - TTrackModifier(handler) { } - TTrackTangentList tangents; - - TTrackPoint calcPoint(double originalIndex) override; + using TTrackInterpolator::TTrackInterpolator; + TTrackPoint interpolate(double index) override; }; - TTrackTangent calcTangent(const TTrack &track, int index) const; + static TTrackTangent calcTangent(const TTrack &track, int index); void modifyTrack( const TTrack &track, diff --git a/toonz/sources/include/tools/modifiers/modifiertest.h b/toonz/sources/include/tools/modifiers/modifiertest.h index e410547..4732695 100644 --- a/toonz/sources/include/tools/modifiers/modifiertest.h +++ b/toonz/sources/include/tools/modifiers/modifiertest.h @@ -26,28 +26,31 @@ class DVAPI TModifierTest : public TInputModifier { public: - class DVAPI Handler : public TTrackHandler { + class DVAPI Handler : public TMultiTrackHandler { public: + const double radius; std::vector angles; - Handler(const TTrack &original) : TTrackHandler(original) {} + inline explicit Handler(double radius): + radius(std::max(TConsts::epsilon, radius)) { } }; - class DVAPI Modifier : public TTrackModifier { + class DVAPI Interpolator : public TTrackInterpolator { public: - double angle; - double radius; - double speed; - - Modifier(TTrackHandler &handler, double angle, double radius, - double speed = 0.25); - TTrackPoint calcPoint(double originalIndex) override; + const double angle; + const double radius; + const double speed; + inline Interpolator(TTrack &track, double angle, double radius, double speed): + TTrackInterpolator(track), angle(angle), radius(radius), speed(speed) { } + TTrackPoint interpolateFromOriginal(double originalIndex); + TTrackPoint interpolate(double index) override; }; public: - const int count; - const double radius; + int count; + double radius; + double speed; - TModifierTest(int count, double radius); + TModifierTest(int count = 3, double radius = 40, double speed = 0.25); void modifyTrack(const TTrack &track, TTrackList &outTracks) override; diff --git a/toonz/sources/include/tools/track.h b/toonz/sources/include/tools/track.h index c9268d4..a8177b3 100644 --- a/toonz/sources/include/tools/track.h +++ b/toonz/sources/include/tools/track.h @@ -37,13 +37,15 @@ class TTrack; class TTrackPoint; class TTrackTangent; class TTrackHandler; -class TTrackToolHandler; -class TTrackModifier; +class TSubTrackHandler; +class TMultiTrackHandler; +class TTrackInterpolator; typedef TSmartPointerT TTrackP; typedef TSmartPointerT TTrackHandlerP; -typedef TSmartPointerT TTrackToolHandlerP; -typedef TSmartPointerT TTrackModifierP; +typedef TSmartPointerT TSubTrackHandlerP; +typedef TSmartPointerT TMultiTrackHandlerP; +typedef TSmartPointerT TTrackInterpolatorP; typedef std::vector TTrackPointList; typedef std::vector TTrackTangentList; @@ -53,21 +55,15 @@ typedef std::vector TTrackList; //***************************************************************************************** -// TTrackToolHandler definition -//***************************************************************************************** - -class DVAPI TTrackToolHandler : public TSmartObject { }; - - -//***************************************************************************************** // export template implementations for win32 //***************************************************************************************** #ifdef _WIN32 template class DVAPI TSmartPointerT; template class DVAPI TSmartPointerT; -template class DVAPI TSmartPointerT; -template class DVAPI TSmartPointerT; +template class DVAPI TSmartPointerT; +template class DVAPI TSmartPointerT; +template class DVAPI TSmartPointerT; #endif @@ -133,28 +129,38 @@ public: // TTrackHandler definition //***************************************************************************************** -class DVAPI TTrackHandler : public TSmartObject { +class DVAPI TTrackHandler : public TSmartObject { }; + + +//***************************************************************************************** +// TSubTrackHandler definition +//***************************************************************************************** + +class DVAPI TSubTrackHandler: public TTrackHandler { public: - const TTrack &original; - std::vector tracks; - TTrackHandler(const TTrack &original): - original(original) { } + TTrackP track; }; //***************************************************************************************** -// TTrackModifier definition +// TMultiTrackHandler definition //***************************************************************************************** -class DVAPI TTrackModifier : public TSmartObject { +class DVAPI TMultiTrackHandler: public TTrackHandler { public: - TTrackHandler &handler; - const TTrack &original; - const double timeOffset; + std::vector tracks; +}; + + +//***************************************************************************************** +// TTrackInterpolator definition +//***************************************************************************************** - explicit TTrackModifier(TTrackHandler &handler, double timeOffset = 0.0): - handler(handler), original(handler.original), timeOffset(timeOffset) { } - virtual TTrackPoint calcPoint(double originalIndex); +class DVAPI TTrackInterpolator : public TSmartObject { +public: + TTrack &track; + inline explicit TTrackInterpolator(TTrack &track); + virtual TTrackPoint interpolate(double index) = 0; }; @@ -177,15 +183,19 @@ public: const TInputState::ButtonHistory::Holder buttonHistory; const bool hasPressure; const bool hasTilt; - const TTrackModifierP modifier; + const TTrack* const original; + const double timeOffset; + const double rootTimeOffset; + mutable TTrackHandlerP handler; - mutable TTrackToolHandlerP toolHandler; mutable int pointsRemoved; mutable int pointsAdded; mutable int fixedPointsAdded; private: + friend class TTrackInterpolator; + TTrackInterpolatorP interpolator; TTrackPointList m_points; const TTrackPoint m_none; int m_pointsFixed; @@ -198,15 +208,17 @@ public: const TInputState::KeyHistory::Holder &keyHistory = TInputState::KeyHistory::Holder(), const TInputState::ButtonHistory::Holder &buttonHistory = TInputState::ButtonHistory::Holder(), bool hasPressure = false, - bool hasTilt = false + bool hasTilt = false, + double timeOffset = 0 ); - explicit TTrack(const TTrackModifierP &modifier); + explicit TTrack(const TTrack &original, double timeOffset = 0); + + const TTrackInterpolatorP& getInterpolator() const + { return interpolator; } + void removeInterpolator() + { interpolator.reset(); } - inline const TTrack* original() const - { return modifier ? &modifier->original : NULL; } - inline double timeOffset() const - { return modifier ? modifier->timeOffset : 0.0; } inline TTimerTicks ticks() const { return keyHistory.ticks(); } inline bool changed() const @@ -217,12 +229,14 @@ public: inline int clampIndex(int index) const { return std::min(std::max(index, 0), size() - 1); } + inline double clampIndexFloat(double index) const + { return std::min(std::max(index, 0.0), (double)(size() - 1)); } inline int floorIndexNoClamp(double index) const { return (int)floor(index + TConsts::epsilon); } inline int floorIndex(double index) const { return clampIndex(floorIndexNoClamp(index)); } inline int ceilIndexNoClamp(double index) const - { return (int)ceil(index - TConsts::epsilon); } + { return floorIndexNoClamp(index) + 1; } inline int ceilIndex(double index) const { return clampIndex(ceilIndexNoClamp(index)); } @@ -287,15 +301,15 @@ public: inline TInputState::KeyState::Holder getKeyState(double time) const { return keyHistory.get(time); } inline TInputState::KeyState::Holder getKeyState(const TTrackPoint &point) const - { return getKeyState(timeOffset() + point.time); } + { return getKeyState(rootTimeOffset + point.time); } inline TInputState::KeyState::Holder getCurrentKeyState() const - { return getKeyState(timeOffset() + current().time); } + { return getKeyState(rootTimeOffset + current().time); } inline TInputState::ButtonState::Holder getButtonState(double time) const { return buttonHistory.get(time); } inline TInputState::ButtonState::Holder getButtonState(const TTrackPoint &point) const - { return getButtonState(timeOffset() + point.time); } + { return getButtonState(rootTimeOffset + point.time); } inline TInputState::ButtonState::Holder getCurrentButtonState() const - { return getButtonState(timeOffset() + current().time); } + { return getButtonState(rootTimeOffset + current().time); } private: template @@ -345,11 +359,25 @@ public: return interpolationLinear(p0.length, p1.length, frac); } - TTrackPoint calcPoint(double index) const; + inline TTrackPoint calcPoint(double index) const + { return interpolator ? interpolator->interpolate(index) : interpolateLinear(index); } TPointD calcTangent(double index, double distance = 0.1) const; double rootIndexByIndex(double index) const; TTrackPoint calcRootPoint(double index) const; + inline TTrackPoint pointFromOriginal(const TTrackPoint &originalPoint, double originalIndex) const { + TTrackPoint p = originalPoint; + p.originalIndex = original ? original->clampIndexFloat(originalIndex) : originalIndex; + p.time -= timeOffset; + return p; + } + + inline TTrackPoint pointFromOriginal(int originalIndex) const + { return original ? pointFromOriginal(original->point(originalIndex), originalIndex) : TTrackPoint(); } + + inline TTrackPoint calcPointFromOriginal(double originalIndex) const + { return original ? pointFromOriginal(original->calcPoint(originalIndex), originalIndex) : TTrackPoint(); } + inline TTrackPoint interpolateLinear(double index) const { double frac; const TTrackPoint &p0 = floorPoint(index, &frac); @@ -407,4 +435,24 @@ public: }; + +//***************************************************************************************** +// TTrackInterpolator implemantation +//***************************************************************************************** + +inline TTrackInterpolator::TTrackInterpolator(TTrack &track): + track(track) { track.interpolator = this; } + + +//***************************************************************************************** +// TTrackIntrOrig definition +//***************************************************************************************** + +class DVAPI TTrackIntrOrig : public TTrackInterpolator { +public: + using TTrackInterpolator::TTrackInterpolator; + TTrackPoint interpolate(double index) override; +}; + + #endif diff --git a/toonz/sources/tnztools/fullcolorbrushtool.cpp b/toonz/sources/tnztools/fullcolorbrushtool.cpp index c89c0ad..91b0aad 100644 --- a/toonz/sources/tnztools/fullcolorbrushtool.cpp +++ b/toonz/sources/tnztools/fullcolorbrushtool.cpp @@ -150,7 +150,7 @@ FullColorBrushTool::FullColorBrushTool(std::string name) m_inputmanager.setHandler(this); #ifndef NDEBUG - m_modifierTest = new TModifierTest(5, 40); + m_modifierTest = new TModifierTest(); #endif m_modifierLine = new TModifierLine(); m_modifierTangents = new TModifierTangents(); @@ -305,8 +305,8 @@ bool FullColorBrushTool::askWrite(const TRect &rect) { //-------------------------------------------------------------------------------------------------- bool FullColorBrushTool::preLeftButtonDown() { - m_modifierAssistants->drawOnly = !m_assistants.getValue(); - m_inputmanager.drawPreview = false; //!m_modifierAssistants->drawOnly; + m_modifierAssistants->magnetism = m_assistants.getValue() ? 1 : 0; + m_inputmanager.drawPreview = false; //!m_modifierAssistants->drawOnly; m_inputmanager.clearModifiers(); m_inputmanager.addModifier(TInputModifierP(m_modifierTangents.getPointer())); @@ -342,7 +342,7 @@ void FullColorBrushTool::handleMouseEvent(MouseEventType type, bool control = e.getModifiersMask() & TMouseEvent::CTRL_KEY; if (shift && type == ME_DOWN && e.button() == Qt::LeftButton && !m_started) { - m_modifierAssistants->drawOnly = true; + m_modifierAssistants->magnetism = 0; m_inputmanager.clearModifiers(); m_inputmanager.addModifier(TInputModifierP(m_modifierLine.getPointer())); m_inputmanager.addModifier( @@ -519,14 +519,14 @@ void FullColorBrushTool::inputPaintTrackPoint(const TTrackPoint &point, // init brush TrackHandler *handler; - if (track.size() == track.pointsAdded && !track.toolHandler && m_workRaster) { + if (track.size() == track.pointsAdded && !track.handler && m_workRaster) { mypaint::Brush mypaintBrush; applyToonzBrushSettings(mypaintBrush); handler = new TrackHandler(m_workRaster, *this, mypaintBrush); handler->brush.beginStroke(); - track.toolHandler = handler; + track.handler = handler; } - handler = dynamic_cast(track.toolHandler.getPointer()); + handler = dynamic_cast(track.handler.getPointer()); if (!handler) return; // paint stroke diff --git a/toonz/sources/tnztools/fullcolorbrushtool.h b/toonz/sources/tnztools/fullcolorbrushtool.h index cdb8450..903ccbd 100644 --- a/toonz/sources/tnztools/fullcolorbrushtool.h +++ b/toonz/sources/tnztools/fullcolorbrushtool.h @@ -42,7 +42,7 @@ class FullColorBrushTool final : public TTool, public TInputHandler { Q_DECLARE_TR_FUNCTIONS(FullColorBrushTool) public: - class TrackHandler : public TTrackToolHandler { + class TrackHandler : public TTrackHandler { public: MyPaintToonzBrush brush; diff --git a/toonz/sources/tnztools/inputmanager.cpp b/toonz/sources/tnztools/inputmanager.cpp index 06b7f8d..8e05e3b 100644 --- a/toonz/sources/tnztools/inputmanager.cpp +++ b/toonz/sources/tnztools/inputmanager.cpp @@ -33,27 +33,28 @@ TInputModifier::modifyTrack( TTrackList &outTracks ) { if (!track.handler) { - track.handler = new TTrackHandler(track); - track.handler->tracks.push_back( - new TTrack( - new TTrackModifier(*track.handler) )); + TSubTrackHandler *handler = new TSubTrackHandler(); + track.handler = handler; + handler->track = new TTrack(track); + new TTrackIntrOrig(*handler->track); } - outTracks.insert( - outTracks.end(), - track.handler->tracks.begin(), - track.handler->tracks.end() ); - if (!track.changed()) + TSubTrackHandler *handler = dynamic_cast(track.handler.getPointer()); + if (!handler) return; + + outTracks.push_back(handler->track); + TTrack &subTrack = *handler->track; + if (!track.changed()) + return; + int start = std::max(0, track.size() - track.pointsAdded); - for(TTrackList::const_iterator ti = track.handler->tracks.begin(); ti != track.handler->tracks.end(); ++ti) { - TTrack &subTrack = **ti; - subTrack.truncate(start); - for(int i = start; i < track.size(); ++i) - subTrack.push_back( subTrack.modifier->calcPoint(i), false ); - subTrack.fix_to(track.fixedSize()); - } + subTrack.truncate(start); + for(int i = start; i < track.size(); ++i) + subTrack.push_back(subTrack.pointFromOriginal(i), false); + subTrack.fix_to(track.fixedSize()); + track.resetChanges(); } @@ -190,7 +191,7 @@ TInputHandler::inputPaintTracks(const TTrackList &tracks) { const TTrack &t = **i; if (t.pointsAdded > 0) { TTimerTicks ticks = t.ticks(); - double timeOffset = t.timeOffset() + t.current().time; + double timeOffset = t.rootTimeOffset + t.current().time; if (!track || (ticks - minTicks)*TToolTimer::frequency + timeOffset - minTimeOffset < 0.0) { track = *i; minTicks = ticks; @@ -494,7 +495,7 @@ TInputManager::trackEvent( TTrackP track = getTrack(deviceId, touchId, ticks, (bool)pressure, (bool)tilt); if (!track->finished()) { ticks = fixTicks(ticks); - double time = (double)(ticks - track->ticks())*TToolTimer::step - track->timeOffset(); + double time = (double)(ticks - track->ticks())*TToolTimer::step - track->rootTimeOffset; addTrackPoint( track, position, diff --git a/toonz/sources/tnztools/modifiers/modifierassistants.cpp b/toonz/sources/tnztools/modifiers/modifierassistants.cpp index 597e97d..c6fec6f 100644 --- a/toonz/sources/tnztools/modifiers/modifierassistants.cpp +++ b/toonz/sources/tnztools/modifiers/modifierassistants.cpp @@ -20,20 +20,15 @@ //***************************************************************************************** -// TModifierAssistants::Modifier implementation +// TModifierAssistants::Interpolator implementation //***************************************************************************************** -TModifierAssistants::Modifier::Modifier(TTrackHandler &handler): - TTrackModifier(handler), - initialized() -{ } - - TTrackPoint -TModifierAssistants::Modifier::calcPoint(double originalIndex) { - TTrackPoint p = TTrackModifier::calcPoint(originalIndex); - return guidelines.empty() ? p : guidelines.front()->smoothTransformPoint(p); +TModifierAssistants::Interpolator::interpolate(double index) { + TTrackPoint p = track.original ? track.calcPointFromOriginal(index) + : track.interpolateLinear(index); + return guidelines.empty() ? p : guidelines.front()->smoothTransformPoint(p, magnetism); } @@ -42,8 +37,8 @@ TModifierAssistants::Modifier::calcPoint(double originalIndex) { //***************************************************************************************** -TModifierAssistants::TModifierAssistants(bool drawOnly): - drawOnly(drawOnly), +TModifierAssistants::TModifierAssistants(double magnetism): + magnetism(magnetism), sensitiveLength(50.0) { } @@ -99,7 +94,7 @@ TModifierAssistants::scanAssistants( if (findGuidelines) for(int i = 0; i < positionsCount; ++i) assistant->getGuidelines(positions[i], imageToTrack, *outGuidelines); - if (draw) assistant->draw(viewer, !drawOnly); + if (draw) assistant->draw(viewer, magnetism > 0); if (!doSomething) return true; } @@ -116,29 +111,35 @@ TModifierAssistants::modifyTrack( TTrackList &outTracks ) { if (!track.handler) { - track.handler = new TTrackHandler(track); - Modifier *modifier = new Modifier(*track.handler); - track.handler->tracks.push_back(new TTrack(modifier)); + Handler *handler = new Handler(); + track.handler = handler; + handler->track = new TTrack(track); + new Interpolator(*handler->track, magnetism); } - - outTracks.push_back(track.handler->tracks.front()); - TTrack &subTrack = *track.handler->tracks.front(); - if (!track.changed()) + + Handler *handler = dynamic_cast(track.handler.getPointer()); + if (!handler) return; - Modifier *modifier = dynamic_cast(subTrack.modifier.getPointer()); - if (!modifier) + + outTracks.push_back(handler->track); + TTrack &subTrack = *handler->track; + Interpolator *intr = dynamic_cast(subTrack.getInterpolator().getPointer()); + if (!intr) return; - + + if (!track.changed()) + return; + // remove points int start = track.size() - track.pointsAdded; if (start < 0) start = 0; - if (!drawOnly && start <= 0) { - modifier->guidelines.clear(); - scanAssistants(&track[0].position, 1, &modifier->guidelines, false, true); + if (intr->magnetism && start <= 0) { + intr->guidelines.clear(); + scanAssistants(&track[0].position, 1, &intr->guidelines, false, true); } - bool fixed = subTrack.fixedSize() || modifier->guidelines.size() <= 1; + bool fixed = subTrack.fixedSize() || intr->guidelines.size() <= 1; // select guideline if (!fixed) @@ -152,11 +153,11 @@ TModifierAssistants::modifyTrack( if (!objHandle->isSpline()) trackToScreen *= TScale(viewer->getDpiScale().x, viewer->getDpiScale().y); trackToScreen *= viewer->get3dViewMatrix().get2d(); - TGuidelineP guideline = TGuideline::findBest(modifier->guidelines, track, trackToScreen, fixed); - if (guideline != modifier->guidelines.front()) - for(int i = 1; i < (int)modifier->guidelines.size(); ++i) - if (modifier->guidelines[i] == guideline) { - std::swap(modifier->guidelines[i], modifier->guidelines.front()); + TGuidelineP guideline = TGuideline::findBest(intr->guidelines, track, trackToScreen, fixed); + if (guideline != intr->guidelines.front()) + for(int i = 1; i < (int)intr->guidelines.size(); ++i) + if (intr->guidelines[i] == guideline) { + std::swap(intr->guidelines[i], intr->guidelines.front()); start = 0; break; } @@ -165,7 +166,7 @@ TModifierAssistants::modifyTrack( // add points subTrack.truncate(start); for(int i = start; i < track.size(); ++i) - subTrack.push_back( modifier->calcPoint(i), false ); + subTrack.push_back( intr->interpolate(i), false ); // fix points if (fixed || track.fixedFinished()) @@ -185,16 +186,20 @@ TModifierAssistants::calcDrawBounds(const TTrackList&, const THoverList&) { void TModifierAssistants::drawTrack(const TTrack &track) { - if (!track.handler) return; - TTrack &subTrack = *track.handler->tracks.front(); - if (Modifier *modifier = dynamic_cast(subTrack.modifier.getPointer())) { - const TGuidelineList &guidelines = modifier->guidelines; - if (!guidelines.empty()) { - guidelines.front()->draw(true); - for(TGuidelineList::const_iterator i = guidelines.begin() + 1; i != guidelines.end(); ++i) - (*i)->draw(); - } - } + Handler *handler = dynamic_cast(track.handler.getPointer()); + if (!handler) return; + + TTrack &subTrack = *handler->track; + Interpolator *intr = dynamic_cast(subTrack.getInterpolator().getPointer()); + if (!intr) return; + + const TGuidelineList &guidelines = intr->guidelines; + if (guidelines.empty()) + return; + + guidelines.front()->draw(true); + for(TGuidelineList::const_iterator i = guidelines.begin() + 1; i != guidelines.end(); ++i) + (*i)->draw(); } @@ -205,8 +210,8 @@ TModifierAssistants::draw(const TTrackList &tracks, const THoverList &hovers) { if (tracks.empty()) // hide hovers if track exists allHovers.insert(allHovers.end(), hovers.begin(), hovers.end()); for(TTrackList::const_iterator i = tracks.begin(); i != tracks.end(); ++i) - if ((*i)->handler && !(*i)->handler->tracks.empty() && !(*i)->handler->tracks.front()->empty()) - allHovers.push_back( (*i)->handler->tracks.front()->back().position ); + if (Handler *handler = dynamic_cast((*i)->handler.getPointer())) + allHovers.push_back( handler->track->back().position ); // draw assistants TGuidelineList guidelines; @@ -219,7 +224,7 @@ TModifierAssistants::draw(const TTrackList &tracks, const THoverList &hovers) { // draw guidelines for(TGuidelineList::const_iterator i = guidelines.begin(); i != guidelines.end(); ++i) - (*i)->draw(false, !drawOnly); + (*i)->draw(false, magnetism > 0); // draw tracks TInputModifier::drawTracks(tracks); diff --git a/toonz/sources/tnztools/modifiers/modifierline.cpp b/toonz/sources/tnztools/modifiers/modifierline.cpp index e678914..382589a 100644 --- a/toonz/sources/tnztools/modifiers/modifierline.cpp +++ b/toonz/sources/tnztools/modifiers/modifierline.cpp @@ -2,10 +2,13 @@ #include + + //***************************************************************************************** // TModifierLine implementation //***************************************************************************************** + static inline void calcFixedAngle(const TTrackPoint &p0, TTrackPoint &p1) { TPointD p = p1.position - p0.position; double l = sqrt(p.x * p.x + p.y * p.y); @@ -20,70 +23,51 @@ static inline void calcFixedAngle(const TTrackPoint &p0, TTrackPoint &p1) { p1.position = p0.position + p; } -TTrackPoint TModifierLine::Modifier::calcPoint(double originalIndex) { - if (original.empty()) return TTrackPoint(); - if (original.size() < 2) return original.front(); - TTrackPoint p0 = original.front(); - TTrackPoint p1 = original.back(); - if (fixAngle) calcFixedAngle(p0, p1); - return TTrack::interpolationLinear(p0, p1, - originalIndex / (original.size() - 1)); -} void TModifierLine::modifyTrack(const TTrack &track, TTrackList &outTracks) { if (!track.handler) { - track.handler = new TTrackHandler(track); - Modifier *modifier = new Modifier(*track.handler); - track.handler->tracks.push_back(new TTrack(modifier)); + Handler *handler = new Handler(); + track.handler = handler; + handler->track = new TTrack(track); } - if (!track.changed()) return; - if (track.handler->tracks.empty()) return; - - TTrack &subTrack = *track.handler->tracks.front(); - Modifier *modifier = dynamic_cast(subTrack.modifier.getPointer()); - if (!modifier) { - track.resetChanges(); + Handler *handler = dynamic_cast(track.handler.getPointer()); + if (!handler) + return; + + outTracks.push_back(handler->track); + TTrack &subTrack = *handler->track; + + if (!track.changed()) return; - } - bool fixAngle = track.getKeyState(track.back()).isPressed(TKey::control); - outTracks.push_back(track.handler->tracks.front()); + subTrack.truncate(0); + // calc max pressure int i1 = track.size(); int i0 = i1 - track.pointsAdded; - double maxPressure = modifier->maxPressure; + double maxPressure = handler->maxPressure; if (track.pointsRemoved) { maxPressure = 0; i0 = 0; } - for (int i = i0; i < i1; ++i) { + for(int i = i0; i < i1; ++i) { double p = track[i].pressure; if (maxPressure < p) maxPressure = p; } - modifier->maxPressure = maxPressure; - modifier->fixAngle = fixAngle; - - subTrack.truncate(0); - - if (track.size() > 0) { - TTrackPoint p = track.front(); - p.originalIndex = 0; - p.pressure = maxPressure; - p.tilt = TPointD(); - subTrack.push_back(p, false); - } - + handler->maxPressure = maxPressure; + + if (track.size() > 0) + subTrack.push_back(subTrack.pointFromOriginal(0), false); + if (track.size() > 1) { - TTrackPoint p = track.back(); - p.originalIndex = track.size() - 1; - p.pressure = maxPressure; - p.tilt = TPointD(); - if (fixAngle) calcFixedAngle(subTrack.front(), p); + TTrackPoint p = subTrack.pointFromOriginal(track.size() - 1); + if (track.getKeyState(track.back()).isPressed(TKey::control)) + calcFixedAngle(subTrack.front(), p); subTrack.push_back(p, false); } - + if (track.fixedFinished()) subTrack.fix_all(); diff --git a/toonz/sources/tnztools/modifiers/modifiersegmentation.cpp b/toonz/sources/tnztools/modifiers/modifiersegmentation.cpp index ba1232e..4718afc 100644 --- a/toonz/sources/tnztools/modifiers/modifiersegmentation.cpp +++ b/toonz/sources/tnztools/modifiers/modifiersegmentation.cpp @@ -42,7 +42,7 @@ TModifierSegmentation::addSegments( } --level; - TTrackPoint p = track.modifier->calcPoint(0.5*(p0.originalIndex + p1.originalIndex)); + TTrackPoint p = track.calcPointFromOriginal(0.5*(p0.originalIndex + p1.originalIndex)); addSegments(track, p0, p, level); addSegments(track, p, p1, level); } @@ -54,21 +54,22 @@ TModifierSegmentation::modifyTrack( TTrackList &outTracks ) { if (!track.handler) { - track.handler = new TTrackHandler(track); - track.handler->tracks.push_back( - new TTrack( - new TTrackModifier(*track.handler) )); + Handler *handler = new Handler(); + track.handler = handler; + handler->track = new TTrack(track); + new Interpolator(*handler->track); } - if (track.handler->tracks.empty()) + Handler *handler = dynamic_cast(track.handler.getPointer()); + if (!handler) return; - - TTrack &subTrack = *track.handler->tracks.front(); - outTracks.push_back(track.handler->tracks.front()); - + + outTracks.push_back(handler->track); + TTrack &subTrack = *handler->track; + if (!track.changed()) return; - + // remove points int start = track.size() - track.pointsAdded; if (start < 0) start = 0; @@ -76,9 +77,9 @@ TModifierSegmentation::modifyTrack( subTrack.truncate(subStart); // add points - TTrackPoint p0 = subTrack.modifier->calcPoint(start - 1); + TTrackPoint p0 = subTrack.pointFromOriginal(start - 1); for(int i = start; i < track.size(); ++i) { - TTrackPoint p1 = subTrack.modifier->calcPoint(i); + TTrackPoint p1 = subTrack.pointFromOriginal(i); addSegments(subTrack, p0, p1, m_maxLevel); p0 = p1; } diff --git a/toonz/sources/tnztools/modifiers/modifiersimplify.cpp b/toonz/sources/tnztools/modifiers/modifiersimplify.cpp index df889c0..612af0b 100644 --- a/toonz/sources/tnztools/modifiers/modifiersimplify.cpp +++ b/toonz/sources/tnztools/modifiers/modifiersimplify.cpp @@ -10,12 +10,7 @@ TModifierSimplify::TModifierSimplify(double step): - step() { setStep(step); } - - -void -TModifierSimplify::setStep(double step) - { this->step = std::max(0.0, step); } + step(step) { } void @@ -24,21 +19,22 @@ TModifierSimplify::modifyTrack( TTrackList &outTracks ) { if (!track.handler) { - track.handler = new TTrackHandler(track); - track.handler->tracks.push_back( - new TTrack( - new TTrackModifier(*track.handler) )); + Handler *handler = new Handler(); + track.handler = handler; + handler->track = new TTrack(track); + new Interpolator(*handler->track); } - if (track.handler->tracks.empty()) + Handler *handler = dynamic_cast(track.handler.getPointer()); + if (!handler) return; - - TTrack &subTrack = *track.handler->tracks.front(); - outTracks.push_back(track.handler->tracks.front()); + + outTracks.push_back(handler->track); + TTrack &subTrack = *handler->track; if (!track.changed()) return; - + // remove points int start = track.size() - track.pointsAdded; if (start < 0) start = 0; @@ -52,7 +48,7 @@ TModifierSimplify::modifyTrack( double step2 = step*step; TTrackPoint p0 = subTrack.back(); for(int i = start; i < track.size(); ++i) { - const TTrackPoint &p1 = track[i]; + const TTrackPoint &p1 = subTrack.pointFromOriginal(i); if (!subTrack.empty() && tdistance2(p1.position, p0.position) < step2) { if (p0.pressure < p1.pressure) p0.pressure = p1.pressure; if (i == track.size() - 1) p0.position = p1.position; @@ -63,7 +59,6 @@ TModifierSimplify::modifyTrack( subTrack.push_back(p0, false); } else { p0 = p1; - p0.originalIndex = i; subTrack.push_back(p0, false); } } diff --git a/toonz/sources/tnztools/modifiers/modifiersmooth.cpp b/toonz/sources/tnztools/modifiers/modifiersmooth.cpp index 953ea68..ac0b212 100644 --- a/toonz/sources/tnztools/modifiers/modifiersmooth.cpp +++ b/toonz/sources/tnztools/modifiers/modifiersmooth.cpp @@ -4,38 +4,14 @@ #include -//***************************************************************************************** -// TModifierSmooth::Modifier implementation -//***************************************************************************************** - - -TModifierSmooth::Modifier::Modifier(TTrackHandler &handler, int radius): - TTrackModifier(handler), - radius(std::max(radius, 0)), - smoothedTrack() -{ } - - -TTrackPoint -TModifierSmooth::Modifier::calcPoint(double originalIndex) { - return smoothedTrack - ? smoothedTrack->interpolateLinear(originalIndex + radius) - : TTrackModifier::calcPoint(originalIndex); -} - //***************************************************************************************** // TModifierSmooth implementation //***************************************************************************************** -TModifierSmooth::TModifierSmooth(int radius): m_radius() - { setRadius(radius); } - - -void -TModifierSmooth::setRadius(int radius) - { m_radius = std::max(0, radius); } +TModifierSmooth::TModifierSmooth(int radius): + radius(radius) { } void @@ -43,32 +19,25 @@ TModifierSmooth::modifyTrack( const TTrack &track, TTrackList &outTracks ) { - if (!m_radius) { - TInputModifier::modifyTrack(track, outTracks); - return; - } + int radius = abs(this->radius); - if (!track.handler) { - track.handler = new TTrackHandler(track); - Modifier *modifier = new Modifier(*track.handler, m_radius); - modifier->smoothedTrack = new TTrack(modifier); - track.handler->tracks.push_back(modifier->smoothedTrack); + if (!track.handler && radius) { + Handler *handler = new Handler(radius); + track.handler = handler; + handler->track = new TTrack(track); } - if (track.handler->tracks.empty()) - return; - - TTrack &subTrack = *track.handler->tracks.front(); - outTracks.push_back(track.handler->tracks.front()); - + Handler *handler = dynamic_cast(track.handler.getPointer()); + if (!handler) + return TInputModifier::modifyTrack(track, outTracks); + + radius = handler->radius; + outTracks.push_back(handler->track); + TTrack &subTrack = *handler->track; + if (!track.changed()) return; - Modifier *modifier = dynamic_cast(subTrack.modifier.getPointer()); - if (!modifier) - return; - int radius = modifier->radius; - // remove points int start = std::max(0, track.size() - track.pointsAdded); subTrack.truncate(start); @@ -87,18 +56,23 @@ TModifierSmooth::modifyTrack( if (i < start) continue; - int oi = track.clampIndex(i - radius); - const TTrackPoint &p = track[oi]; - subTrack.push_back( - TTrackPoint( - accum.position*k, - accum.pressure*k, - accum.tilt*k, - oi, - p.time, - 0, - p.final ), - false ); + double originalIndex; + if (i <= radius) { + originalIndex = i/(double)(radius + 1); + } else + if (i >= size - radius - 1) { + originalIndex = track.size() - 1 - (size - i - 1)/(double)(radius + 1); + } else { + originalIndex = i - radius; + } + + TTrackPoint p = subTrack.pointFromOriginal(i - radius); + p.position = accum.position*k; + p.pressure = accum.pressure*k; + p.tilt = accum.tilt*k; + p.originalIndex = originalIndex; + p.final = p.final && i == size - 1; + subTrack.push_back(p, false); const TTrackPoint &p0 = track[i - 2*radius]; accum.position -= p0.position; diff --git a/toonz/sources/tnztools/modifiers/modifiertangents.cpp b/toonz/sources/tnztools/modifiers/modifiertangents.cpp index 60a8704..e1cfcd7 100644 --- a/toonz/sources/tnztools/modifiers/modifiertangents.cpp +++ b/toonz/sources/tnztools/modifiers/modifiertangents.cpp @@ -4,22 +4,22 @@ //***************************************************************************************** -// TModifierTangents::Modifier implementation +// TModifierTangents::Interpolator implementation //***************************************************************************************** TTrackPoint -TModifierTangents::Modifier::calcPoint(double originalIndex) { +TModifierTangents::Interpolator::interpolate(double index) { double frac; - int i0 = original.floorIndex(originalIndex, &frac); + int i0 = track.floorIndex(index, &frac); int i1 = i0 + 1; TTrackPoint p; // calculate tangent length to make monotonic subdivisions, // (because we don't have valid input time) - const TTrackPoint &p0 = original[i0]; - const TTrackPoint &p1 = original[i1]; + const TTrackPoint &p0 = track[i0]; + const TTrackPoint &p1 = track[i1]; TTrackTangent t0 = i0 >= 0 && i0 < (int)tangents.size() ? tangents[i0] : TTrackTangent(); TTrackTangent t1 = i1 >= 0 && i1 < (int)tangents.size() ? tangents[i1] : TTrackTangent(); double l = p1.length - p0.length; @@ -36,9 +36,7 @@ TModifierTangents::Modifier::calcPoint(double originalIndex) { t1.tilt.x *= l; t1.tilt.y *= l; - p = TTrack::interpolationSpline(p0, p1, t0, t1, frac); - p.originalIndex = originalIndex; - return p; + return TTrack::interpolationSpline(p0, p1, t0, t1, frac); } @@ -48,7 +46,7 @@ TModifierTangents::Modifier::calcPoint(double originalIndex) { TTrackTangent -TModifierTangents::calcTangent(const TTrack &track, int index) const { +TModifierTangents::calcTangent(const TTrack &track, int index) { if (index <= 0 || index >= track.size() - 1) return TTrackTangent(); @@ -60,7 +58,7 @@ TModifierTangents::calcTangent(const TTrack &track, int index) const { // instead of time when message dispatched //double k = p2.time - p0.time; - // calculate tangent based on length, util we have no valid times + // calculate tangent based on length, until we have no valid times double k = p2.length - p0.length; k = k > TConsts::epsilon ? 1/k : 0; @@ -77,39 +75,39 @@ TModifierTangents::modifyTrack( TTrackList &outTracks ) { if (!track.handler) { - track.handler = new TTrackHandler(track); - track.handler->tracks.push_back( - new TTrack( - new Modifier(*track.handler) )); + Handler *handler = new Handler(); + track.handler = handler; + handler->track = new TTrack(track); + new Interpolator(*handler->track); } - - if (track.handler->tracks.empty()) + + Handler *handler = dynamic_cast(track.handler.getPointer()); + if (!handler) return; - - TTrack &subTrack = *track.handler->tracks.front(); - Modifier *modifier = dynamic_cast(subTrack.modifier.getPointer()); - if (!modifier) + + outTracks.push_back(handler->track); + TTrack &subTrack = *handler->track; + Interpolator *intr = dynamic_cast(subTrack.getInterpolator().getPointer()); + if (!intr) return; - - outTracks.push_back(track.handler->tracks.front()); + if (!track.changed()) return; - // update subTrack int start = track.size() - track.pointsAdded; - if (start > 1) --start; if (start < 0) start = 0; - subTrack.truncate(start); - for(int i = start; i < track.size(); ++i) { - TTrackPoint p = track[i]; - p.originalIndex = i; - subTrack.push_back(p, false); - } // update tangents - modifier->tangents.resize(start); + int tangentStart = start - 1; + if (tangentStart < 0) tangentStart = 0; + intr->tangents.resize(tangentStart); + for(int i = tangentStart; i < track.size(); ++i) + intr->tangents.push_back(calcTangent(track, i)); + + // update subTrack + subTrack.truncate(start); for(int i = start; i < track.size(); ++i) - modifier->tangents.push_back(calcTangent(track, i)); + subTrack.push_back(subTrack.pointFromOriginal(i), false); // fix points if (track.fixedFinished()) { diff --git a/toonz/sources/tnztools/modifiers/modifiertest.cpp b/toonz/sources/tnztools/modifiers/modifiertest.cpp index 7801f3b..72f4774 100644 --- a/toonz/sources/tnztools/modifiers/modifiertest.cpp +++ b/toonz/sources/tnztools/modifiers/modifiertest.cpp @@ -6,111 +6,117 @@ // std includes #include + //***************************************************************************************** -// TModifierTest::Modifier implementation +// TModifierTest::Interpolator 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 > TConsts::epsilon) { - double frac; - int i0 = original.floorIndex(originalIndex, &frac); - int i1 = original.ceilIndex(originalIndex); - if (i0 < 0) return p; - - if (Handler *handler = dynamic_cast(&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 = - original.calcTangent(originalIndex, fabs(2.0 * this->radius / speed)); - p.position.x -= tangent.y * s * radius; - p.position.y += tangent.x * s * radius; - p.pressure *= 1.0 - 0.5 * c; - } - } else { - p.pressure = 0.0; - } +TTrackPoint TModifierTest::Interpolator::interpolateFromOriginal(double originalIndex) { + Handler *handler = track.original + ? dynamic_cast(track.original->handler.getPointer()) + : nullptr; + if (!handler) + return track.interpolateLinear(track.indexByOriginalIndex(originalIndex)); + + TTrackPoint p = track.calcPointFromOriginal(originalIndex); + + double frac; + int i0 = track.original->floorIndex(originalIndex, &frac); + int i1 = track.original->ceilIndex(originalIndex); + + double angle = TTrack::interpolationLinear( + handler->angles[i0], handler->angles[i1], frac ); + angle = angle*speed + this->angle; + + double r = radius*p.pressure; + double s = sin(angle); + + double d = fabs(2.0*radius); + if (fabs(speed) > TConsts::epsilon) + d /= fabs(speed); + + TPointD tangent = track.original->calcTangent(originalIndex, d); + p.position.x -= tangent.y * s * r; + p.position.y += tangent.x * s * r; + p.pressure *= fabs(s); return p; } + +TTrackPoint TModifierTest::Interpolator::interpolate(double index) { + return interpolateFromOriginal(track.originalIndexByIndex(index)); +} + + //***************************************************************************************** // TModifierTest implementation //***************************************************************************************** -TModifierTest::TModifierTest(int count, double radius) - : count(count), radius(radius) {} +TModifierTest::TModifierTest(int count, double radius, double speed) + : count(count), radius(radius), speed(speed) {} void TModifierTest::modifyTrack(const TTrack &track, TTrackList &outTracks) { const double segmentSize = 2.0 * M_PI / 10.0; - if (!track.handler) { - if (track.getKeyState(track.front().time).isPressed(TKey(Qt::Key_Alt))) { - // 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, 0.25))); + if ( !track.handler + && track.getKeyState(track.front().time).isPressed(TKey::alt) ) + { + Handler *handler = new Handler(this->radius); + track.handler = handler; + for (int i = 0; i < count; ++i) { + handler->tracks.push_back(new TTrack(track)); + TTrack &subTrack = *handler->tracks.back(); + new Interpolator(subTrack, i*2*M_PI/(double)count, radius, 0.25); } } - - Handler *handler = dynamic_cast(track.handler.getPointer()); - if (!handler) { - TInputModifier::modifyTrack(track, outTracks); + + Handler *handler = dynamic_cast(track.handler.getPointer()); + if (!handler) + return TInputModifier::modifyTrack(track, outTracks); + + outTracks.insert(outTracks.end(), handler->tracks.begin(), handler->tracks.end()); + if (!track.changed()) return; - } - - outTracks.insert(outTracks.end(), track.handler->tracks.begin(), - track.handler->tracks.end()); - if (!track.changed()) return; + double radius = handler->radius; int start = track.size() - track.pointsAdded; if (start < 0) start = 0; // remove angles - double lastAngle = start < (int)handler->angles.size() - ? handler->angles[start] - : handler->angles.empty() ? 0.0 - : handler->angles.back(); - handler->angles.resize(start, lastAngle); - + handler->angles.resize(start); + // 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 > TConsts::epsilon - ? dl / (radius * track[i].pressure) - : 0.0; - handler->angles.push_back(handler->angles[i - 1] + da); + for(int i = start; i < track.size(); ++i) { + if (i) { + const TTrackPoint &p0 = track[i - 1]; + const TTrackPoint &p1 = track[i]; + double dl = p1.length - p0.length; + double da = p1.pressure > TConsts::epsilon + ? dl / (radius * p1.pressure) + : 0.0; + handler->angles.push_back(handler->angles.back() + 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; + for(TTrackList::const_iterator ti = handler->tracks.begin(); ti != handler->tracks.end(); ++ti) { + TTrack &subTrack = **ti; + Interpolator *intr = dynamic_cast(subTrack.getInterpolator().getPointer()); + if (!intr) + continue; + double currentSegmentSize = segmentSize; - if (const Modifier *modifier = - dynamic_cast(subTrack.modifier.getPointer())) - if (fabs(modifier->speed) > TConsts::epsilon) - currentSegmentSize = segmentSize / fabs(modifier->speed); + if (fabs(intr->speed) > TConsts::epsilon) + currentSegmentSize /= fabs(intr->speed); // remove points - int subStart = - subTrack.floorIndex(subTrack.indexByOriginalIndex(start - 1)) + 1; + int subStart = start > 0 + ? subTrack.floorIndex(subTrack.indexByOriginalIndex(start - 1)) + 1 + : 0; subTrack.truncate(subStart); // add points @@ -123,18 +129,20 @@ void TModifierTest::modifyTrack(const TTrack &track, 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), false); + intr->interpolateFromOriginal(i - 1 + frac), false ); } } - subTrack.push_back(subTrack.modifier->calcPoint(i), false); + subTrack.push_back(intr->interpolateFromOriginal(i), false); } // fix points + if (track.fixedFinished()) + subTrack.fix_all(); if (track.fixedSize()) subTrack.fix_to( subTrack.floorIndex(subTrack.indexByOriginalIndex(track.fixedSize() - 1)) + 1 ); } - + track.resetChanges(); } diff --git a/toonz/sources/tnztools/toonzrasterbrushtool.cpp b/toonz/sources/tnztools/toonzrasterbrushtool.cpp index 9bfafd6..c3935bc 100644 --- a/toonz/sources/tnztools/toonzrasterbrushtool.cpp +++ b/toonz/sources/tnztools/toonzrasterbrushtool.cpp @@ -782,7 +782,7 @@ ToonzRasterBrushTool::ToonzRasterBrushTool(std::string name, int targetType) for(int i = 0; i < 3; ++i) m_modifierSmooth[i] = new TModifierSmooth(); #ifndef NDEBUG - m_modifierTest = new TModifierTest(5, 40); + m_modifierTest = new TModifierTest(); #endif m_inputmanager.addModifier( @@ -1040,15 +1040,15 @@ bool ToonzRasterBrushTool::askWrite(const TRect &rect) { bool ToonzRasterBrushTool::preLeftButtonDown() { int smoothRadius = (int)round(m_smooth.getValue()); - m_modifierAssistants->drawOnly = !m_assistants.getValue(); - m_inputmanager.drawPreview = false; //!m_modifierAssistants->drawOnly; + m_modifierAssistants->magnetism = m_assistants.getValue() ? 1 : 0; + m_inputmanager.drawPreview = false; //!m_modifierAssistants->drawOnly; m_inputmanager.clearModifiers(); m_inputmanager.addModifier(TInputModifierP(m_modifierTangents.getPointer())); if (smoothRadius > 0) { m_inputmanager.addModifier(TInputModifierP(m_modifierSmoothSegmentation.getPointer())); for(int i = 0; i < 3; ++i) { - m_modifierSmooth[i]->setRadius(smoothRadius); + m_modifierSmooth[i]->radius = smoothRadius; m_inputmanager.addModifier(TInputModifierP(m_modifierSmooth[i].getPointer())); } } @@ -1080,7 +1080,7 @@ void ToonzRasterBrushTool::handleMouseEvent(MouseEventType type, bool control = e.getModifiersMask() & TMouseEvent::CTRL_KEY; if (shift && type == ME_DOWN && e.button() == Qt::LeftButton && !m_painting.active) { - m_modifierAssistants->drawOnly = true; + m_modifierAssistants->magnetism = 0; m_inputmanager.clearModifiers(); m_inputmanager.addModifier(TInputModifierP(m_modifierLine.getPointer())); m_inputmanager.addModifier(TInputModifierP(m_modifierAssistants.getPointer())); @@ -1265,8 +1265,8 @@ void ToonzRasterBrushTool::inputPaintTrackPoint(const TTrackPoint &point, const // first point must be without handler, following points must be with handler // other behaviour is possible bug and must be ignored - assert(firstPoint == !track.toolHandler); - if (firstPoint != !track.toolHandler) + assert(firstPoint == !track.handler); + if (firstPoint != !track.handler) return; if (m_painting.myPaint.isActive) { @@ -1277,9 +1277,9 @@ void ToonzRasterBrushTool::inputPaintTrackPoint(const TTrackPoint &point, const if (firstPoint) { handler = new MyPaintStroke(m_workRas, *this, m_painting.myPaint.baseBrush, false); handler->brush.beginStroke(); - track.toolHandler = handler; + track.handler = handler; } - handler = dynamic_cast(track.toolHandler.getPointer()); + handler = dynamic_cast(track.handler.getPointer()); if (!handler) return; // paint stroke @@ -1323,9 +1323,9 @@ void ToonzRasterBrushTool::inputPaintTrackPoint(const TTrackPoint &point, const getAboveStyleIdSet(m_painting.styleId, ri->getPalette(), aboveStyleIds); handler->brush.setAboveStyleIds(aboveStyleIds); } - track.toolHandler = handler; + track.handler = handler; } - handler = dynamic_cast(track.toolHandler.getPointer()); + handler = dynamic_cast(track.handler.getPointer()); if (!handler) return; // paint stroke @@ -1358,9 +1358,9 @@ void ToonzRasterBrushTool::inputPaintTrackPoint(const TTrackPoint &point, const getAboveStyleIdSet(m_painting.styleId, ri->getPalette(), aboveStyleIds); handler->brush.setAboveStyleIds(aboveStyleIds); } - track.toolHandler = handler; + track.handler = handler; } - handler = dynamic_cast(track.toolHandler.getPointer()); + handler = dynamic_cast(track.handler.getPointer()); if (!handler) return; // paint stroke diff --git a/toonz/sources/tnztools/toonzrasterbrushtool.h b/toonz/sources/tnztools/toonzrasterbrushtool.h index 370649e..7bbe6b5 100644 --- a/toonz/sources/tnztools/toonzrasterbrushtool.h +++ b/toonz/sources/tnztools/toonzrasterbrushtool.h @@ -175,7 +175,7 @@ protected: TSmartPointerT m_modifierTest; #endif - class MyPaintStroke: public TTrackToolHandler { + class MyPaintStroke: public TTrackHandler { public: MyPaintToonzBrush brush; @@ -189,7 +189,7 @@ protected: { } }; - class PencilStroke: public TTrackToolHandler { + class PencilStroke: public TTrackHandler { public: RasterStrokeGenerator brush; @@ -202,7 +202,7 @@ protected: { } }; - class BluredStroke: public TTrackToolHandler { + class BluredStroke: public TTrackHandler { public: BluredBrush brush; diff --git a/toonz/sources/tnztools/toonzvectorbrushtool.cpp b/toonz/sources/tnztools/toonzvectorbrushtool.cpp index edd576d..11645f6 100644 --- a/toonz/sources/tnztools/toonzvectorbrushtool.cpp +++ b/toonz/sources/tnztools/toonzvectorbrushtool.cpp @@ -592,7 +592,7 @@ ToonzVectorBrushTool::ToonzVectorBrushTool(std::string name, int targetType) m_modifierSmooth[i] = new TModifierSmooth(); m_modifierSimplify = new TModifierSimplify(); #ifndef NDEBUG - m_modifierTest = new TModifierTest(5, 40); + m_modifierTest = new TModifierTest(); #endif m_inputmanager.addModifier( @@ -957,7 +957,7 @@ void ToonzVectorBrushTool::inputSetBusy(bool busy) { //-------------------------------------------------------------------------------------------------- void ToonzVectorBrushTool::inputPaintTracks(const TTrackList &tracks) { - if (tracks.size() != 1 || !tracks.front()) return; + if (tracks.empty()) return; TRectD invalidateRect; @@ -996,11 +996,12 @@ void ToonzVectorBrushTool::inputPaintTracks(const TTrackList &tracks) { bool ToonzVectorBrushTool::preLeftButtonDown() { if (getViewer() && getViewer()->getGuidedStrokePickerMode()) return false; + m_pixelSize = getPixelSize(); int smoothRadius = (int)round(m_smooth.getValue()); - m_modifierAssistants->drawOnly = !m_assistants.getValue(); + m_modifierAssistants->magnetism = m_assistants.getValue() ? 1 : 0; m_modifierSegmentation->setStep(TPointD(m_pixelSize, m_pixelSize)); m_modifierSmoothSegmentation->setStep(TPointD(2*m_pixelSize, 2*m_pixelSize)); - m_modifierSimplify->setStep(2*m_pixelSize); + m_modifierSimplify->step = 2*m_pixelSize; m_inputmanager.drawPreview = false; m_inputmanager.clearModifiers(); @@ -1008,7 +1009,7 @@ bool ToonzVectorBrushTool::preLeftButtonDown() { if (smoothRadius > 0) { m_inputmanager.addModifier(TInputModifierP(m_modifierSmoothSegmentation.getPointer())); for(int i = 0; i < 3; ++i) { - m_modifierSmooth[i]->setRadius(smoothRadius); + m_modifierSmooth[i]->radius = smoothRadius; m_inputmanager.addModifier(TInputModifierP(m_modifierSmooth[i].getPointer())); } } @@ -1041,7 +1042,7 @@ void ToonzVectorBrushTool::handleMouseEvent(MouseEventType type, bool control = e.getModifiersMask() & TMouseEvent::CTRL_KEY; if (shift && type == ME_DOWN && e.button() == Qt::LeftButton && !m_active) { - m_modifierAssistants->drawOnly = true; + m_modifierAssistants->magnetism = 0; m_inputmanager.clearModifiers(); m_inputmanager.addModifier(TInputModifierP(m_modifierLine.getPointer())); m_inputmanager.addModifier(TInputModifierP(m_modifierAssistants.getPointer())); diff --git a/toonz/sources/tnztools/track.cpp b/toonz/sources/tnztools/track.cpp index 5af347a..2637216 100644 --- a/toonz/sources/tnztools/track.cpp +++ b/toonz/sources/tnztools/track.cpp @@ -11,14 +11,13 @@ TTrack::Id TTrack::m_lastId = 0; //***************************************************************************************** -// TTrackModifier implemantation +// TTrackIntrOrig implemantation //***************************************************************************************** TTrackPoint -TTrackModifier::calcPoint(double originalIndex) { - TTrackPoint p = original.calcPoint(originalIndex); - p.originalIndex = originalIndex; - return p; +TTrackIntrOrig::interpolate(double index) { + return track.original ? track.calcPointFromOriginal(track.originalIndexByIndex(index)) + : track.interpolateLinear(index); } @@ -32,7 +31,8 @@ TTrack::TTrack( const TInputState::KeyHistory::Holder &keyHistory, const TInputState::ButtonHistory::Holder &buttonHistory, bool hasPressure, - bool hasTilt + bool hasTilt, + double timeOffset ): id(++m_lastId), deviceId(deviceId), @@ -41,21 +41,26 @@ TTrack::TTrack( buttonHistory(buttonHistory), hasPressure(hasPressure), hasTilt(hasTilt), + original(), + timeOffset(timeOffset), + rootTimeOffset(timeOffset), pointsRemoved(), pointsAdded(), fixedPointsAdded(), m_pointsFixed() { } -TTrack::TTrack(const TTrackModifierP &modifier): +TTrack::TTrack(const TTrack &original, double timeOffset): id(++m_lastId), - deviceId(modifier->original.deviceId), - touchId(modifier->original.touchId), - keyHistory(modifier->original.keyHistory), - buttonHistory(modifier->original.buttonHistory), - hasPressure(modifier->original.hasPressure), - hasTilt(modifier->original.hasTilt), - modifier(modifier), + deviceId(original.deviceId), + touchId(original.touchId), + keyHistory(original.keyHistory), + buttonHistory(original.buttonHistory), + hasPressure(original.hasPressure), + hasTilt(original.hasTilt), + original(&original), + timeOffset(timeOffset), + rootTimeOffset(original.rootTimeOffset + timeOffset), pointsRemoved(), pointsAdded(), fixedPointsAdded(), @@ -64,15 +69,15 @@ TTrack::TTrack(const TTrackModifierP &modifier): const TTrack* TTrack::root() const - { return original() ? original()->root() : this; } + { return original ? original->root() : this; } int TTrack::level() const - { return original() ? original()->level() + 1 : 0; } + { return original ? original->level() + 1 : 0; } int TTrack::floorIndex(double index, double *outFrac) const { - int i = (int)floor(index + TConsts::epsilon); + int i = floorIndexNoClamp(index); if (i > size() - 1) { if (outFrac) *outFrac = 0.0; return size() - 1; @@ -87,10 +92,13 @@ TTrack::floorIndex(double index, double *outFrac) const { void TTrack::push_back(const TTrackPoint &point, bool fixed) { + assert(m_points.empty() || !m_points.back().final); m_points.push_back(point); - if (size() > 1) { + TTrackPoint &p = m_points.back(); + if (m_points.size() <= 1) { + p.length = 0; + } else { const TTrackPoint &prev = *(m_points.rbegin() + 1); - TTrackPoint &p = m_points.back(); // fix originalIndex if (p.originalIndex < prev.originalIndex) @@ -100,8 +108,7 @@ TTrack::push_back(const TTrackPoint &point, bool fixed) { p.time = std::max(p.time, prev.time + TToolTimer::step); // calculate length - TPointD d = p.position - prev.position; - p.length = prev.length + sqrt(d.x*d.x + d.y*d.y); + p.length = prev.length + tdistance(p.position, prev.position); } ++pointsAdded; if (fixed) fix_all(); @@ -130,13 +137,6 @@ TTrack::fix_points(int count) { } -TTrackPoint -TTrack::calcPoint(double index) const { - return modifier - ? modifier->calcPoint( originalIndexByIndex(index) ) - : interpolateLinear(index); -} - TPointD TTrack::calcTangent(double index, double distance) const { double minDistance = 10.0*TConsts::epsilon; @@ -150,14 +150,14 @@ TTrack::calcTangent(double index, double distance) const { double TTrack::rootIndexByIndex(double index) const { - return modifier - ? modifier->original.rootIndexByIndex( originalIndexByIndex(index) ) + return original + ? original->rootIndexByIndex( originalIndexByIndex(index) ) : index; } TTrackPoint TTrack::calcRootPoint(double index) const { - return modifier - ? modifier->original.calcRootPoint( originalIndexByIndex(index) ) + return original + ? original->calcRootPoint( originalIndexByIndex(index) ) : calcPoint(index); } diff --git a/toonz/sources/toonzlib/strokegenerator.cpp b/toonz/sources/toonzlib/strokegenerator.cpp index 755a928..cac636b 100644 --- a/toonz/sources/toonzlib/strokegenerator.cpp +++ b/toonz/sources/toonzlib/strokegenerator.cpp @@ -159,10 +159,10 @@ void StrokeGenerator::drawFragments(int first, int last) { if (b.thick == 0) b.thick = 0.1; } // m_p0 = m_p1 = b; - v = a.thick * normalize(rotate90(b - a)); + v = a.thick * normalizeOrZero(rotate90(b - a)); m_p0 = a + v; m_p1 = a - v; - v = b.thick * normalize(rotate90(b - a)); + v = b.thick * normalizeOrZero(rotate90(b - a)); TPointD p0 = b + v; TPointD p1 = b - v; glBegin(GL_POLYGON); @@ -190,11 +190,11 @@ void StrokeGenerator::drawFragments(int first, int last) { if (c.thick == 0) c.thick = 0.1; } if (i - 1 == 0) { - v = a.thick * normalize(rotate90(b - a)); + v = a.thick * normalizeOrZero(rotate90(b - a)); m_p0 = a + v; m_p1 = a - v; } - v = b.thick * normalize(rotate90(c - a)); + v = b.thick * normalizeOrZero(rotate90(c - a)); TPointD p0 = b + v; TPointD p1 = b - v; glBegin(GL_POLYGON); @@ -214,7 +214,7 @@ void StrokeGenerator::drawFragments(int first, int last) { } if (last < 2) return; v = m_points[last].thick * - normalize(rotate90(m_points[last] - m_points[last - 1])); + normalizeOrZero(rotate90(m_points[last] - m_points[last - 1])); TPointD p0 = m_points[last] + v; TPointD p1 = m_points[last] - v; glBegin(GL_POLYGON);