diff --git a/toonz/sources/include/tools/inputmanager.h b/toonz/sources/include/tools/inputmanager.h index f3e9548..50563d8 100644 --- a/toonz/sources/include/tools/inputmanager.h +++ b/toonz/sources/include/tools/inputmanager.h @@ -272,6 +272,9 @@ private: std::vector m_tracks; std::vector m_hovers; TInputSavePoint::List m_savePoints; + TRectD m_prevBounds; + TRectD m_nextBounds; + bool m_started; int m_savePointsSent; static TInputState::TouchId m_lastTouchId; diff --git a/toonz/sources/include/tools/modifiers/modifierline.h b/toonz/sources/include/tools/modifiers/modifierline.h new file mode 100644 index 0000000..a6966a2 --- /dev/null +++ b/toonz/sources/include/tools/modifiers/modifierline.h @@ -0,0 +1,47 @@ +#pragma once + +#ifndef MODIFIERLINE_INCLUDED +#define MODIFIERLINE_INCLUDED + +// TnzTools includes +#include + + +#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 + + +//=================================================================== + +//***************************************************************************************** +// TModifierLine definition +//***************************************************************************************** + +class TModifierLine: public TInputModifier { +public: + class Modifier: public TTrackModifier { + public: + explicit Modifier(TTrackHandler &handler): + TTrackModifier(handler), fixAngle(), maxPressure() { } + + bool fixAngle; + double maxPressure; + TInputSavePoint::Holder savePoint; + + TTrackPoint calcPoint(double originalIndex) override; + }; + + void modifyTrack( + const TTrack &track, + const TInputSavePoint::Holder &savePoint, + TTrackList &outTracks ) override; +}; + +#endif diff --git a/toonz/sources/include/tools/tooltimer.h b/toonz/sources/include/tools/tooltimer.h index 60f6df5..d20513b 100644 --- a/toonz/sources/include/tools/tooltimer.h +++ b/toonz/sources/include/tools/tooltimer.h @@ -39,8 +39,7 @@ public: static const double step; static const double epsilon; - static inline TTimerTicks ticks() - { return m_instance.m_timer.nsecsElapsed(); } + static TTimerTicks ticks(); }; diff --git a/toonz/sources/include/tools/track.h b/toonz/sources/include/tools/track.h index dd83e29..52efd44 100644 --- a/toonz/sources/include/tools/track.h +++ b/toonz/sources/include/tools/track.h @@ -37,10 +37,12 @@ class TTrack; class TTrackPoint; class TTrackTangent; class TTrackHandler; +class TTrackToolHandler; class TTrackModifier; typedef TSmartPointerT TTrackP; typedef TSmartPointerT TTrackHandlerP; +typedef TSmartPointerT TTrackToolHandlerP; typedef TSmartPointerT TTrackModifierP; typedef std::vector TTrackPointList; @@ -51,6 +53,13 @@ typedef std::vector TTrackList; //***************************************************************************************** +// TTrackToolHandler definition +//***************************************************************************************** + +class DVAPI TTrackToolHandler : public TSmartObject { }; + + +//***************************************************************************************** // TTrackPoint definition //***************************************************************************************** @@ -159,6 +168,7 @@ public: const TTrackModifierP modifier; mutable TTrackHandlerP handler; + mutable TTrackToolHandlerP toolHandler; mutable int pointsRemoved; mutable int pointsAdded; @@ -242,6 +252,11 @@ public: inline const TTrackPoint& current() const { return point(size() - pointsAdded); } + inline const TTrackPoint& previous() const + { return point(size() - pointsAdded - 1); } + inline const TTrackPoint& next() const + { return point(size() - pointsAdded + 1); } + inline TInputState::KeyState::Holder getKeyState(double time) const { return keyHistory.get(time); } inline TInputState::KeyState::Holder getKeyState(const TTrackPoint &point) const diff --git a/toonz/sources/tnztools/CMakeLists.txt b/toonz/sources/tnztools/CMakeLists.txt index 9e67138..8f0d9fc 100644 --- a/toonz/sources/tnztools/CMakeLists.txt +++ b/toonz/sources/tnztools/CMakeLists.txt @@ -49,10 +49,11 @@ set(HEADERS ../include/tools/track.h ../include/tools/inputmanager.h ../include/tools/assistant.h - ../include/tools/modifiers/modifiertest.h + ../include/tools/modifiers/modifierassistants.h + ../include/tools/modifiers/modifierline.h ../include/tools/modifiers/modifiertangents.h + ../include/tools/modifiers/modifiertest.h ../include/tools/modifiers/modifiersegmentation.h - ../include/tools/modifiers/modifierassistants.h ) set(SOURCES @@ -121,10 +122,11 @@ set(SOURCES track.cpp inputmanager.cpp assistant.cpp - modifiers/modifiertest.cpp + modifiers/modifierassistants.cpp + modifiers/modifierline.cpp modifiers/modifiertangents.cpp + modifiers/modifiertest.cpp modifiers/modifiersegmentation.cpp - modifiers/modifierassistants.cpp assistants/guidelineline.cpp assistants/assistantvanishingpoint.cpp editassistantstool.cpp diff --git a/toonz/sources/tnztools/fullcolorbrushtool.cpp b/toonz/sources/tnztools/fullcolorbrushtool.cpp index 771a9d6..f1dc3e0 100644 --- a/toonz/sources/tnztools/fullcolorbrushtool.cpp +++ b/toonz/sources/tnztools/fullcolorbrushtool.cpp @@ -126,16 +126,17 @@ FullColorBrushTool::FullColorBrushTool(std::string name) , m_enabledPressure(false) , m_minCursorThick(0) , m_maxCursorThick(0) - , m_toonz_brush(0) , m_tileSet(0) , m_tileSaver(0) , m_notifier(0) , m_presetsLoaded(false) - , m_firstTime(true) { + , m_firstTime(true) + , m_started(false) { bind(TTool::RasterImage | TTool::EmptyTarget); m_inputmanager.setHandler(this); m_modifierTest = new TModifierTest(5, 40); + m_modifierLine = new TModifierLine(); m_modifierTangents = new TModifierTangents(); m_modifierAssistants = new TModifierAssistants(); m_modifierSegmentation = new TModifierSegmentation(0.25); @@ -156,8 +157,6 @@ FullColorBrushTool::FullColorBrushTool(std::string name) m_modifierEraser.setId("RasterEraser"); m_modifierLockAlpha.setId("LockAlpha"); m_pressure.setId("PressureSensitivity"); - - m_brushTimer.start(); } //--------------------------------------------------------------------------------------------------- @@ -320,6 +319,13 @@ void FullColorBrushTool::handleMouseEvent(MouseEventType type, const TPointD &po bool alt = e.getModifiersMask() & TMouseEvent::ALT_KEY; bool shift = e.getModifiersMask() & TMouseEvent::SHIFT_KEY; bool control = e.getModifiersMask() & TMouseEvent::CTRL_KEY; + + if ((control || shift) && type == ME_DOWN && e.button() == Qt::LeftButton && !m_started) { + m_inputmanager.clearModifiers(); + m_inputmanager.addModifier( TInputModifierP(m_modifierLine.getPointer()) ); + m_inputmanager.addModifier( TInputModifierP(m_modifierSegmentation.getPointer()) ); + } + if (alt != m_inputmanager.state.isKeyPressed(TKey::alt)) m_inputmanager.keyEvent(alt, TKey::alt, t, nullptr); if (shift != m_inputmanager.state.isKeyPressed(TKey::shift)) @@ -350,220 +356,6 @@ void FullColorBrushTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e) void FullColorBrushTool::mouseMove(const TPointD &pos, const TMouseEvent &e) { handleMouseEvent(ME_MOVE, pos, e); } -//--------------------------------------------------------------------------------------------------- - -void FullColorBrushTool::inputLeftButtonDown( - const TTrackPoint &point, const TTrack &track ) -{ - const TPointD &pos = point.position; - TPointD previousBrushPos = m_brushPos; - m_brushPos = m_mousePos = pos; - m_mousePressed = true; - TToolViewer *viewer = getViewer(); - if (!viewer) return; - - TRasterImageP ri = (TRasterImageP)getImage(true); - if (!ri) ri = (TRasterImageP)touchImage(); - - if (!ri) return; - - // Modifier to do straight line - TInputState::KeyState::Holder keys = track.getKeyState(point); - if (keys.isPressed(TKey::shift) || keys.isPressed(TKey::control)) { - m_isStraight = true; - m_firstPoint = pos; - m_lastPoint = pos; - } - - /* update color here since the current style might be switched with numpad - * shortcut keys */ - updateCurrentStyle(); - - TRasterP ras = ri->getRaster(); - - if (!(m_workRaster && m_backUpRas)) setWorkAndBackupImages(); - - m_workRaster->lock(); - - TPointD rasCenter = ras->getCenterD(); - TPointD pt(pos + rasCenter); - - double defPressure = 1.0; - if (getApplication()->getCurrentLevelStyle()->getTagId() == 4001) // mypaint brush case - defPressure = 0.5; - double pressure = m_enabledPressure && track.hasPressure ? point.pressure : defPressure; - - m_tileSet = new TTileSetFullColor(ras->getSize()); - m_tileSaver = new TTileSaverFullColor(ras, m_tileSet); - - mypaint::Brush mypaintBrush; - applyToonzBrushSettings(mypaintBrush); - m_toonz_brush = new MyPaintToonzBrush(m_workRaster, *this, mypaintBrush, false); - - m_strokeRect.empty(); - m_strokeSegmentRect.empty(); - m_toonz_brush->beginStroke(); - m_toonz_brush->strokeTo(pt, pressure, restartBrushTimer()); - TRect updateRect = m_strokeSegmentRect * ras->getBounds(); - if (!updateRect.isEmpty()) - ras->extract(updateRect)->copy(m_workRaster->extract(updateRect)); - - TPointD thickOffset(m_maxCursorThick * 0.5, m_maxCursorThick * 0.5); - TRectD invalidateRect = convert(m_strokeSegmentRect) - rasCenter; - invalidateRect += TRectD(m_brushPos - thickOffset, m_brushPos + thickOffset); - invalidateRect += - TRectD(previousBrushPos - thickOffset, previousBrushPos + thickOffset); - invalidate(invalidateRect.enlarge(2.0)); -} - -//------------------------------------------------------------------------------------------------------------- - -void FullColorBrushTool::inputLeftButtonDrag( - const TTrackPoint &point, const TTrack &track ) -{ - const TPointD &pos = point.position; - TRectD invalidateRect; - TPointD previousLastPoint = m_lastPoint; - m_lastPoint = pos; - - TPointD previousBrushPos = m_brushPos; - m_brushPos = m_mousePos = pos; - TRasterImageP ri = (TRasterImageP)getImage(true); - if (!ri) return; - - if (!m_toonz_brush) return; - - TRasterP ras = ri->getRaster(); - TPointD rasCenter = ras->getCenterD(); - TPointD pt(pos + rasCenter); - - double defPressure = 1.0; - if (getApplication()->getCurrentLevelStyle()->getTagId() == 4001) // mypaint brush case - defPressure = 0.5; - double pressure = m_enabledPressure && track.hasPressure ? point.pressure : defPressure; - - if (m_maxPressure < pressure) m_maxPressure = pressure; - - if (m_isStraight) { - if (track.getKeyState(point).isPressed(TKey::control)) { - TPointD dist = m_lastPoint - m_firstPoint; - double angle = fabs(atan(dist)) * (180 / 3.14159); - if (angle > 90) angle = 180 - angle; - if (angle > 90 - 22.5) - m_lastPoint.x = m_firstPoint.x; - else if (angle < 22.5) - m_lastPoint.y = m_firstPoint.y; - else { - double xDistance = m_lastPoint.x - m_firstPoint.x; - double yDistance = m_lastPoint.y - m_firstPoint.y; - if (abs(xDistance) > abs(yDistance)) { - if (abs(yDistance) == yDistance) - m_lastPoint.y = m_firstPoint.y + abs(xDistance); - else - m_lastPoint.y = m_firstPoint.y - abs(xDistance); - } else { - if (abs(xDistance) == xDistance) - m_lastPoint.x = m_firstPoint.x + abs(yDistance); - else - m_lastPoint.x = m_firstPoint.x - abs(yDistance); - } - } - } - double cursorSize = m_maxCursorThick/2 + 2; - TPointD cursorSize2d(cursorSize, cursorSize); - invalidateRect = TRectD(m_firstPoint, previousLastPoint).enlarge(2); - invalidateRect += TRectD(previousBrushPos - cursorSize2d, previousBrushPos + cursorSize2d); - invalidateRect += TRectD(m_brushPos - cursorSize2d, m_brushPos + cursorSize2d); - invalidateRect += TRectD(m_firstPoint, m_lastPoint).enlarge(2); - invalidate(invalidateRect); - return; - } - - m_strokeSegmentRect.empty(); - m_toonz_brush->strokeTo(pt, pressure, restartBrushTimer()); - TRect updateRect = m_strokeSegmentRect * ras->getBounds(); - if (!updateRect.isEmpty()) - ras->extract(updateRect)->copy(m_workRaster->extract(updateRect)); - - TPointD thickOffset(m_maxCursorThick * 0.5, m_maxCursorThick * 0.5); - invalidateRect = convert(m_strokeSegmentRect) - rasCenter; - invalidateRect += TRectD(m_brushPos - thickOffset, m_brushPos + thickOffset); - invalidateRect += - TRectD(previousBrushPos - thickOffset, previousBrushPos + thickOffset); - invalidate(invalidateRect.enlarge(2.0)); -} - -//--------------------------------------------------------------------------------------------------------------- - -void FullColorBrushTool::inputLeftButtonUp( - const TTrackPoint &point, const TTrack &track ) -{ - const TPointD &pos = point.position; - TPointD previousBrushPos = m_brushPos; - m_brushPos = m_mousePos = pos; - - TRasterImageP ri = (TRasterImageP)getImage(true); - if (!ri) return; - - if (!m_toonz_brush) return; - - TRasterP ras = ri->getRaster(); - TPointD rasCenter = ras->getCenterD(); - TPointD pt; - if (m_isStraight) - pt = TPointD(m_lastPoint + rasCenter); - else - pt = TPointD(pos + rasCenter); - - double defPressure = 1.0; - if (getApplication()->getCurrentLevelStyle()->getTagId() == 4001) // mypaint brush case - defPressure = 0.5; - double pressure = m_enabledPressure && track.hasPressure ? point.pressure : defPressure; - - if (m_isStraight && m_maxPressure > 0.0) - pressure = m_maxPressure; - - m_strokeSegmentRect.empty(); - m_toonz_brush->strokeTo(pt, pressure, restartBrushTimer()); - m_toonz_brush->endStroke(); - TRect updateRect = m_strokeSegmentRect * ras->getBounds(); - if (!updateRect.isEmpty()) - ras->extract(updateRect)->copy(m_workRaster->extract(updateRect)); - - TPointD thickOffset(m_maxCursorThick * 0.5, m_maxCursorThick * 0.5); - TRectD invalidateRect = convert(m_strokeSegmentRect) - rasCenter; - invalidateRect += TRectD(m_brushPos - thickOffset, m_brushPos + thickOffset); - invalidateRect += - TRectD(previousBrushPos - thickOffset, previousBrushPos + thickOffset); - invalidate(invalidateRect.enlarge(2.0)); - - if (m_toonz_brush) { - delete m_toonz_brush; - m_toonz_brush = 0; - } - - m_lastRect.empty(); - m_workRaster->unlock(); - - if (m_tileSet->getTileCount() > 0) { - delete m_tileSaver; - TTool::Application *app = TTool::getApplication(); - TXshLevel *level = app->getCurrentLevel()->getLevel(); - TXshSimpleLevelP simLevel = level->getSimpleLevel(); - TFrameId frameId = getCurrentFid(); - TRasterP subras = ras->extract(m_strokeRect)->clone(); - TUndoManager::manager()->add(new FullColorBrushUndo( - m_tileSet, simLevel.getPointer(), frameId, m_isFrameCreated, subras, - m_strokeRect.getP00())); - } - - notifyImageChanged(); - m_strokeRect.empty(); - m_mousePressed = false; - m_isStraight = false; - m_maxPressure = -1.0; -} - //--------------------------------------------------------------------------------------------------------------- void FullColorBrushTool::inputMouseMove( @@ -621,6 +413,98 @@ void FullColorBrushTool::inputMouseMove( //------------------------------------------------------------------------------------------------------------- +void FullColorBrushTool::inputSetBusy(bool busy) { + if (m_started == busy) return; + if (busy) { + // begin paint + TRasterImageP ri = (TRasterImageP)getImage(true); + if (!ri) ri = (TRasterImageP)touchImage(); + if (!ri) return; + TRasterP ras = ri->getRaster(); + + if (!(m_workRaster && m_backUpRas)) setWorkAndBackupImages(); + m_workRaster->lock(); + m_tileSet = new TTileSetFullColor(ras->getSize()); + m_tileSaver = new TTileSaverFullColor(ras, m_tileSet); + + // update color here since the current style might be switched + // with numpad shortcut keys + updateCurrentStyle(); + } else { + // end paint + if (TRasterImageP ri = (TRasterImageP)getImage(true)) { + TRasterP ras = ri->getRaster(); + + m_lastRect.empty(); + m_workRaster->unlock(); + + if (m_tileSet->getTileCount() > 0) { + delete m_tileSaver; + TTool::Application *app = TTool::getApplication(); + TXshLevel *level = app->getCurrentLevel()->getLevel(); + TXshSimpleLevelP simLevel = level->getSimpleLevel(); + TFrameId frameId = getCurrentFid(); + TRasterP subras = ras->extract(m_strokeRect)->clone(); + TUndoManager::manager()->add(new FullColorBrushUndo( + m_tileSet, simLevel.getPointer(), frameId, m_isFrameCreated, subras, + m_strokeRect.getP00())); + } + + notifyImageChanged(); + m_strokeRect.empty(); + } + } + m_started = busy; +} + +//------------------------------------------------------------------------------------------------------------- + +void FullColorBrushTool::inputPaintTrackPoint(const TTrackPoint &point, const TTrack &track, bool firstTrack) { + // get raster + if (!m_started || !getViewer()) return; + TRasterImageP ri = (TRasterImageP)getImage(true); + if (!ri) return; + TRasterP ras = ri->getRaster(); + TPointD rasCenter = ras->getCenterD(); + + // init brush + TrackHandler *handler; + if (track.size() == track.pointsAdded && !track.toolHandler && m_workRaster) { + mypaint::Brush mypaintBrush; + applyToonzBrushSettings(mypaintBrush); + handler = new TrackHandler(m_workRaster, *this, mypaintBrush); + handler->brush.beginStroke(); + track.toolHandler = handler; + } + handler = dynamic_cast(track.toolHandler.getPointer()); + if (!handler) return; + + // paint stroke + m_strokeSegmentRect.empty(); + handler->brush.strokeTo( + point.position + rasCenter, + m_enabledPressure ? point.pressure : 0.5, + point.tilt, + point.time - track.previous().time ); + if (track.pointsAdded == 1 && track.finished()) + handler->brush.endStroke(); + + // update affected area + TRect updateRect = m_strokeSegmentRect * ras->getBounds(); + if (!updateRect.isEmpty()) + ras->extract(updateRect)->copy(m_workRaster->extract(updateRect)); + TRectD invalidateRect = convert(m_strokeSegmentRect) - rasCenter; + if (firstTrack) { + TPointD thickOffset(m_maxCursorThick * 0.5, m_maxCursorThick * 0.5); + invalidateRect += TRectD(m_brushPos - thickOffset, m_brushPos + thickOffset); + invalidateRect += TRectD(point.position - thickOffset, point.position + thickOffset); + m_brushPos = m_mousePos = point.position; + } + invalidate(invalidateRect.enlarge(2.0)); +} + +//------------------------------------------------------------------------------------------------------------- + void FullColorBrushTool::inputInvalidateRect(const TRectD &bounds) { invalidate(bounds); } @@ -628,11 +512,6 @@ void FullColorBrushTool::inputInvalidateRect(const TRectD &bounds) void FullColorBrushTool::draw() { if (TRasterImageP ri = TRasterImageP(getImage(false))) { - // Draw line segment on straight line mode - if (m_isStraight) { - tglDrawSegment(m_firstPoint, m_lastPoint); - } - // If toggled off, don't draw brush outline if (!Preferences::instance()->isCursorOutlineEnabled()) return; @@ -906,14 +785,6 @@ void FullColorBrushTool::updateCurrentStyle() { //------------------------------------------------------------------ -double FullColorBrushTool::restartBrushTimer() { - double dtime = m_brushTimer.nsecsElapsed() * 1e-9; - m_brushTimer.restart(); - return dtime; -} - -//------------------------------------------------------------------ - TMyPaintBrushStyle *FullColorBrushTool::getBrushStyle() { if (TTool::Application *app = getApplication()) return dynamic_cast(app->getCurrentLevelStyle()); diff --git a/toonz/sources/tnztools/fullcolorbrushtool.h b/toonz/sources/tnztools/fullcolorbrushtool.h index 67dd22d..50fdfb1 100644 --- a/toonz/sources/tnztools/fullcolorbrushtool.h +++ b/toonz/sources/tnztools/fullcolorbrushtool.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -36,9 +37,21 @@ class Brush; class FullColorBrushTool final : public TTool, public RasterController, public TInputHandler { Q_DECLARE_TR_FUNCTIONS(FullColorBrushTool) +public: + class TrackHandler: public TTrackToolHandler { + public: + MyPaintToonzBrush brush; + + TrackHandler( + const TRaster32P &ras, + RasterController &controller, + const mypaint::Brush &brush + ): + brush(ras, controller, brush) { } + }; +private: void updateCurrentStyle(); - double restartBrushTimer(); void applyClassicToonzBrushSettings(mypaint::Brush &mypaintBrush); void applyToonzBrushSettings(mypaint::Brush &mypaintBrush); @@ -63,10 +76,9 @@ public: void leftButtonUp(const TPointD &pos, const TMouseEvent &e) override; void mouseMove(const TPointD &pos, const TMouseEvent &e) override; - void inputLeftButtonDown(const TTrackPoint &point, const TTrack &track) override; - void inputLeftButtonDrag(const TTrackPoint &point, const TTrack &track) override; - void inputLeftButtonUp(const TTrackPoint &point, const TTrack &track) override; void inputMouseMove(const TPointD &position, const TInputState &state) override; + void inputSetBusy(bool busy) override; + void inputPaintTrackPoint(const TTrackPoint &point, const TTrack &track, bool firstTrack) override; void inputInvalidateRect(const TRectD &bounds) override; TTool* inputGetTool() override { return this; }; @@ -103,21 +115,22 @@ private: protected: TInputManager m_inputmanager; TSmartPointerT m_modifierTest; + TSmartPointerT m_modifierLine; TSmartPointerT m_modifierTangents; TSmartPointerT m_modifierAssistants; TSmartPointerT m_modifierSegmentation; TPropertyGroup m_prop; - TIntPairProperty m_thickness; - TBoolProperty m_pressure; + TIntPairProperty m_thickness; + TBoolProperty m_pressure; TDoublePairProperty m_opacity; - TDoubleProperty m_hardness; - TDoubleProperty m_modifierSize; - TDoubleProperty m_modifierOpacity; - TBoolProperty m_modifierEraser; - TBoolProperty m_modifierLockAlpha; - TEnumProperty m_preset; + TDoubleProperty m_hardness; + TDoubleProperty m_modifierSize; + TDoubleProperty m_modifierOpacity; + TBoolProperty m_modifierEraser; + TBoolProperty m_modifierLockAlpha; + TEnumProperty m_preset; TPixel32 m_currentColor; bool m_enabledPressure; @@ -131,9 +144,6 @@ protected: TRect m_strokeRect, m_strokeSegmentRect, m_lastRect; - MyPaintToonzBrush *m_toonz_brush; - QElapsedTimer m_brushTimer; - TTileSetFullColor *m_tileSet; TTileSaverFullColor *m_tileSaver; @@ -143,12 +153,8 @@ protected: bool m_presetsLoaded; bool m_firstTime; - bool m_mousePressed = false; - bool m_isStraight = false; - TPointD m_firstPoint; - TPointD m_lastPoint; - double m_maxPressure = -1.0; + bool m_started; bool m_propertyUpdating = false; }; diff --git a/toonz/sources/tnztools/inputmanager.cpp b/toonz/sources/tnztools/inputmanager.cpp index 1ddbf00..58546f2 100644 --- a/toonz/sources/tnztools/inputmanager.cpp +++ b/toonz/sources/tnztools/inputmanager.cpp @@ -204,6 +204,7 @@ TInputManager::TInputManager(): m_handler(), m_tracks(1), m_hovers(1), + m_started(), m_savePointsSent() { } @@ -293,6 +294,12 @@ TInputManager::paintTracks() { } TTrackList &subTracks = m_tracks.back(); + // is paint started? + if (!m_started && !subTracks.empty()) { + m_started = true; + if (m_handler) m_handler->inputSetBusy(true); + } + // create handlers for(TTrackList::const_iterator i = subTracks.begin(); i != subTracks.end(); ++i) if (!(*i)->handler) @@ -339,7 +346,10 @@ TInputManager::paintTracks() { } for(std::vector::iterator i = m_tracks.begin(); i != m_tracks.end(); ++i) i->clear(); - if (m_handler) m_handler->inputSetBusy(false); + if (m_started) { + if (m_handler) m_handler->inputSetBusy(false); + m_started = false; + } } break; } @@ -473,8 +483,10 @@ void TInputManager::processTracks() { paintTracks(); TRectD bounds = calcDrawBounds(); - if (!bounds.isEmpty()) - m_handler->inputInvalidateRect(bounds); + if (!bounds.isEmpty()) { + m_handler->inputInvalidateRect(m_prevBounds + bounds); + m_nextBounds += bounds; + } } @@ -489,6 +501,7 @@ void TInputManager::reset() { // forget about handler paint stack // assuime it was already reset by outside + m_started = false; m_savePointsSent = 0; // reset save point @@ -559,9 +572,6 @@ TInputManager::trackEvent( bool final, TTimerTicks ticks ) { - if (getInputTracks().empty() && m_handler) - m_handler->inputSetBusy(true); - ticks = fixTicks(ticks); TTrackP track = getTrack(deviceId, touchId, ticks, (bool)pressure, (bool)tilt); if (!track->finished()) { @@ -629,8 +639,10 @@ TInputManager::hoverEvent(const THoverList &hovers) { } if (m_handler) { TRectD bounds = calcDrawBounds(); - if (!bounds.isEmpty()) - m_handler->inputInvalidateRect(bounds); + if (!bounds.isEmpty()) { + m_handler->inputInvalidateRect(m_prevBounds + bounds); + m_nextBounds += bounds; + } m_handler->inputHoverEvent(*this); } } @@ -667,6 +679,9 @@ TInputManager::calcDrawBounds() { void TInputManager::draw() { + m_prevBounds = m_nextBounds; + m_nextBounds = TRectD(); + // paint not sent sub-tracks if (debugInputManager || m_savePointsSent < (int)m_savePoints.size()) { glPushAttrib(GL_ALL_ATTRIB_BITS); diff --git a/toonz/sources/tnztools/modifiers/modifierline.cpp b/toonz/sources/tnztools/modifiers/modifierline.cpp new file mode 100644 index 0000000..561f636 --- /dev/null +++ b/toonz/sources/tnztools/modifiers/modifierline.cpp @@ -0,0 +1,95 @@ + + +#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); + if (l < TConsts::epsilon) { + p = TPointD(); + } else { + double a = atan2(p.y, p.x); + a = round(a*4/M_PI)*M_PI/4; + p.x = cos(a)*l; + p.y = sin(a)*l; + } + 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, + const TInputSavePoint::Holder &savePoint, + TTrackList &outTracks ) +{ + if (!track.handler) { + track.handler = new TTrackHandler(track); + Modifier *modifier = new Modifier(*track.handler); + modifier->savePoint = savePoint; + track.handler->tracks.push_back( new TTrack(modifier) ); + } + + 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(); return; } + + bool fixAngle = track.getKeyState(track.back()).isPressed(TKey::shift); + outTracks.push_back(track.handler->tracks.front()); + + int i1 = track.size(); + int i0 = i1 - track.pointsAdded; + double maxPressure = modifier->maxPressure; + if (track.pointsRemoved) + { maxPressure = 0; i0 = 0; } + for(int i = i0; i < i1; ++i) { + double p = track[i].pressure; + if (maxPressure < p) maxPressure = p; + } + modifier->maxPressure = maxPressure; + modifier->fixAngle = fixAngle; + if (track.finished()) + modifier->savePoint.reset(); + + subTrack.truncate(0); + + if (track.size() > 0) { + TTrackPoint p = track.front(); + p.originalIndex = 0; + p.pressure = maxPressure; + p.tilt = TPointD(); + subTrack.push_back(p); + } + + 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); + subTrack.push_back(p); + } + + track.resetChanges(); +} diff --git a/toonz/sources/tnztools/mypainttoonzbrush.cpp b/toonz/sources/tnztools/mypainttoonzbrush.cpp index 3f97202..38c3b43 100644 --- a/toonz/sources/tnztools/mypainttoonzbrush.cpp +++ b/toonz/sources/tnztools/mypainttoonzbrush.cpp @@ -59,9 +59,9 @@ class Raster32PMyPaintSurface::Internal public: typedef SurfaceCustom Parent; Internal(Raster32PMyPaintSurface &owner) - : SurfaceCustom(owner.m_ras->pixels(), owner.m_ras->getLx(), - owner.m_ras->getLy(), owner.m_ras->getPixelSize(), - owner.m_ras->getRowSize(), &owner) {} + : SurfaceCustom(owner.ras->pixels(), owner.ras->getLx(), + owner.ras->getLy(), owner.ras->getPixelSize(), + owner.ras->getRowSize(), &owner) {} }; //======================================================= @@ -71,14 +71,14 @@ public: //======================================================= Raster32PMyPaintSurface::Raster32PMyPaintSurface(const TRaster32P &ras) - : m_ras(ras), controller(), internal() { + : ras(ras), controller(), internal() { assert(ras); internal = new Internal(*this); } Raster32PMyPaintSurface::Raster32PMyPaintSurface(const TRaster32P &ras, RasterController &controller) - : m_ras(ras), controller(&controller), internal() { + : ras(ras), controller(&controller), internal() { assert(ras); internal = new Internal(*this); } @@ -115,15 +115,15 @@ MyPaintToonzBrush::MyPaintToonzBrush( const mypaint::Brush &brush, bool interpolation ) - : m_ras(ras) - , m_mypaintSurface(m_ras, controller) + : ras(ras) + , mypaintSurface(ras, controller) , brush(brush) , reset(true) , interpolation(interpolation) { // read brush antialiasing settings float aa = this->brush.getBaseValue(MYPAINT_BRUSH_SETTING_ANTI_ALIASING); - m_mypaintSurface.setAntialiasing(aa > 0.5f); + mypaintSurface.setAntialiasing(aa > 0.5f); // reset brush antialiasing to zero to avoid radius and hardness correction this->brush.setBaseValue(MYPAINT_BRUSH_SETTING_ANTI_ALIASING, 0.f); @@ -141,14 +141,14 @@ void MyPaintToonzBrush::beginStroke() { void MyPaintToonzBrush::endStroke() { if (!reset) { if (interpolation) - strokeTo(TPointD(current.x, current.y), current.pressure, 0.f); + strokeTo(TPointD(current.x, current.y), current.pressure, TPointD(current.tx, current.ty), 0.f); beginStroke(); } } -void MyPaintToonzBrush::strokeTo(const TPointD &point, double pressure, - double dtime) { - Params next(point.x, point.y, pressure, 0.0); +void MyPaintToonzBrush::strokeTo(const TPointD &position, double pressure, + const TPointD &tilt, double dtime) { + Params next(position.x, position.y, pressure, tilt.x, tilt.y, 0.0); if (reset) { current = next; @@ -190,8 +190,8 @@ void MyPaintToonzBrush::strokeTo(const TPointD &point, double pressure, sub->p2.setMedian(sub->p1, segment->p1); segment = sub; } else { - brush.strokeTo(m_mypaintSurface, segment->p2.x, segment->p2.y, - segment->p2.pressure, 0.f, 0.f, + brush.strokeTo(mypaintSurface, segment->p2.x, segment->p2.y, + segment->p2.pressure, segment->p2.tx, segment->p2.ty, segment->p2.time - p0.time); if (segment == stack) break; p0 = segment->p2; @@ -207,7 +207,7 @@ void MyPaintToonzBrush::strokeTo(const TPointD &point, double pressure, previous.time = 0.0; current.time = dtime; } else { - brush.strokeTo(m_mypaintSurface, point.x, point.y, pressure, 0.f, 0.f, dtime); + brush.strokeTo(mypaintSurface, position.x, position.y, pressure, tilt.x, tilt.y, dtime); } } @@ -224,6 +224,6 @@ void MyPaintToonzBrush::updateDrawing(const TRasterCM32P rasCM, if (targetRect.isEmpty()) return; rasCM->copy(rasBackupCM->extract(targetRect), targetRect.getP00()); - putOnRasterCM(rasCM->extract(targetRect), m_ras->extract(targetRect), styleId, + putOnRasterCM(rasCM->extract(targetRect), ras->extract(targetRect), styleId, lockAlpha); } diff --git a/toonz/sources/tnztools/mypainttoonzbrush.h b/toonz/sources/tnztools/mypainttoonzbrush.h index 5304fd7..3eab55b 100644 --- a/toonz/sources/tnztools/mypainttoonzbrush.h +++ b/toonz/sources/tnztools/mypainttoonzbrush.h @@ -27,7 +27,7 @@ class Raster32PMyPaintSurface : public mypaint::Surface { private: class Internal; - TRaster32P m_ras; + TRaster32P ras; RasterController *controller; Internal *internal; @@ -80,6 +80,9 @@ public: bool getAntialiasing() const; void setAntialiasing(bool value); + + RasterController* getController() const + { return controller; } }; //======================================================= @@ -93,16 +96,16 @@ private: struct Params { union { struct { - double x, y, pressure, time; + double x, y, pressure, tx, ty, time; }; struct { - double values[4]; + double values[6]; }; }; - inline explicit Params(double x = 0.0, double y = 0.0, - double pressure = 0.0, double time = 0.0) - : x(x), y(y), pressure(pressure), time(time) {} + inline explicit Params(double x = 0.0, double y = 0.0, double pressure = 0.0, + double tx = 0.0, double ty = 0.0, double time = 0.0) + : x(x), y(y), pressure(pressure), tx(tx), ty(ty), time(time) {} inline void setMedian(Params &a, Params &b) { for (int i = 0; i < (int)sizeof(values) / sizeof(values[0]); ++i) @@ -114,8 +117,8 @@ private: Params p1, p2; }; - TRaster32P m_ras; - Raster32PMyPaintSurface m_mypaintSurface; + TRaster32P ras; + Raster32PMyPaintSurface mypaintSurface; mypaint::Brush brush; bool reset; @@ -129,12 +132,23 @@ public: const mypaint::Brush &brush, bool interpolation = false ); void beginStroke(); + void strokeTo( + const TPointD &position, + double pressure, + const TPointD &tilt, + double dtime ); void endStroke(); - void strokeTo(const TPointD &p, double pressure, double dtime); // colormapped void updateDrawing(const TRasterCM32P rasCM, const TRasterCM32P rasBackupCM, const TRect &bbox, int styleId, bool lockAlpha) const; + + const TRaster32P& getRaster() const + { return ras; } + RasterController& getController() + { return *mypaintSurface.getController(); } + const mypaint::Brush& getBrush() const + { return brush; } }; #endif // T_BLUREDBRUSH diff --git a/toonz/sources/tnztools/tooltimer.cpp b/toonz/sources/tnztools/tooltimer.cpp index 5dfdc15..bebd4db 100644 --- a/toonz/sources/tnztools/tooltimer.cpp +++ b/toonz/sources/tnztools/tooltimer.cpp @@ -10,7 +10,6 @@ const TTimerTicks TToolTimer::frequency = 1000000000; const double TToolTimer::step = 1e-9; const double TToolTimer::epsilon = 1e-10; -TToolTimer TToolTimer::m_instance; //***************************************************************************************** @@ -19,3 +18,9 @@ TToolTimer TToolTimer::m_instance; TToolTimer::TToolTimer() { m_timer.start(); } + + +TTimerTicks TToolTimer::ticks() { + static TToolTimer timer; + return timer.m_timer.nsecsElapsed(); +} diff --git a/toonz/sources/tnztools/toonzrasterbrushtool.cpp b/toonz/sources/tnztools/toonzrasterbrushtool.cpp index 2542d20..0b256e9 100644 --- a/toonz/sources/tnztools/toonzrasterbrushtool.cpp +++ b/toonz/sources/tnztools/toonzrasterbrushtool.cpp @@ -1357,7 +1357,7 @@ void ToonzRasterBrushTool::leftButtonDown(const TPointD &pos, m_strokeRect.empty(); m_strokeSegmentRect.empty(); m_toonz_brush->beginStroke(); - m_toonz_brush->strokeTo(point, pressure, restartBrushTimer()); + m_toonz_brush->strokeTo(point, pressure, TPointD(), restartBrushTimer()); TRect updateRect = m_strokeSegmentRect * ras->getBounds(); if (!updateRect.isEmpty()) { // ras->extract(updateRect)->copy(m_workRas->extract(updateRect)); @@ -1510,7 +1510,7 @@ void ToonzRasterBrushTool::leftButtonDrag(const TPointD &pos, TPointD point(centeredPos + rasCenter); m_strokeSegmentRect.empty(); - m_toonz_brush->strokeTo(point, pressure, restartBrushTimer()); + m_toonz_brush->strokeTo(point, pressure, TPointD(), restartBrushTimer()); TRect updateRect = m_strokeSegmentRect * ras->getBounds(); if (!updateRect.isEmpty()) { // ras->extract(updateRect)->copy(m_workRaster->extract(updateRect)); @@ -1681,7 +1681,7 @@ void ToonzRasterBrushTool::finishRasterBrush(const TPointD &pos, double pressure = m_pressure.getValue() ? pressureVal : 0.5; m_strokeSegmentRect.empty(); - m_toonz_brush->strokeTo(point, pressure, restartBrushTimer()); + m_toonz_brush->strokeTo(point, pressure, TPointD(), restartBrushTimer()); m_toonz_brush->endStroke(); TRect updateRect = m_strokeSegmentRect * ras->getBounds(); if (!updateRect.isEmpty()) { diff --git a/toonz/sources/tnztools/track.cpp b/toonz/sources/tnztools/track.cpp index ae32131..8d048d1 100644 --- a/toonz/sources/tnztools/track.cpp +++ b/toonz/sources/tnztools/track.cpp @@ -107,6 +107,10 @@ TTrack::pop_back(int count) { if (count > size()) count = size(); if (count <= 0) return; m_points.resize(size() - count); + if (pointsAdded > count) + { pointsAdded -= count; return; } + if (pointsAdded > 0) + { count -= pointsAdded; pointsAdded = 0; } pointsRemoved += count; }