diff --git a/toonz/sources/tnztools/controlpointeditortool.cpp b/toonz/sources/tnztools/controlpointeditortool.cpp index 8f25a50..b3caa91 100644 --- a/toonz/sources/tnztools/controlpointeditortool.cpp +++ b/toonz/sources/tnztools/controlpointeditortool.cpp @@ -16,6 +16,7 @@ #include "toonz/tframehandle.h" #include "toonz/tcolumnhandle.h" #include "toonz/txsheethandle.h" +#include "toonz/strokegenerator.h" #include "toonz/txshlevelhandle.h" #include "toonz/tobjecthandle.h" #include "toonz/stage2.h" @@ -27,6 +28,8 @@ using namespace ToolUtils; +TEnv::StringVar CPSelectionType("ControlPointEditorToolSelectionType", + "Rectangular"); TEnv::IntVar AutoSelectDrawing("ControlPointEditorToolAutoSelectDrawing", 1); TEnv::IntVar Snap("ControlPointEditorToolSnap", 0); TEnv::IntVar SnapSensitivity("ControlPointEditorToolSnapSensitivity", 0); @@ -37,6 +40,9 @@ TEnv::IntVar SnapSensitivity("ControlPointEditorToolSnapSensitivity", 0); #define MEDIUM_WSTR L"Medium" #define HIGH_WSTR L"High" +#define RECTANGULAR_WSTR L"Rectangular" +#define FREEHAND_WSTR L"Freehand" + const double SNAPPING_LOW = 5.0; const double SNAPPING_MEDIUM = 25.0; const double SNAPPING_HIGH = 100.0; @@ -138,6 +144,8 @@ class ControlPointEditorTool final : public TTool { TPointD m_pos; TPropertyGroup m_prop; + TEnumProperty m_selectType; + TBoolProperty m_autoSelectDrawing; // Consente di scegliere se swichare tra i livelli. @@ -147,9 +155,14 @@ class ControlPointEditorTool final : public TTool { bool m_foundSnap; TPointD m_snapPoint; + TPointD m_firstPos; // The first point inserted in m_track + StrokeGenerator m_track; // Lazo selection generator. + TStroke *m_stroke; // Stores the stroke generated by m_track. + enum Action { NONE, RECT_SELECTION, + FREEHAND_SELECTION, CP_MOVEMENT, SEGMENT_MOVEMENT, IN_SPEED_MOVEMENT, @@ -162,6 +175,11 @@ class ControlPointEditorTool final : public TTool { TUndo *m_undo; + void selectRegion(TStroke *stroke); + void startFreehand(const TPointD &pos); + void freehandDrag(const TPointD &pos); + void closeFreehand(const TPointD &pos); + public: ControlPointEditorTool(); @@ -292,6 +310,7 @@ ControlPointEditorTool::ControlPointEditorTool() , m_autoSelectDrawing("Auto Select Drawing", true) , m_snap("snap", false) , m_snapSensitivity("Sensitivity:") + , m_selectType("Type:") , m_action(NONE) , m_cursorType(NORMAL) , m_undo(0) @@ -299,11 +318,16 @@ ControlPointEditorTool::ControlPointEditorTool() , m_moveControlPointEditorStroke() , m_moveSegmentLimitation() { bind(TTool::Vectors); + m_prop.bind(m_selectType); m_prop.bind(m_autoSelectDrawing); m_prop.bind(m_snap); m_prop.bind(m_snapSensitivity); m_selection.setControlPointEditorStroke(&m_controlPointEditorStroke); + m_selectType.addValue(RECTANGULAR_WSTR); + m_selectType.addValue(FREEHAND_WSTR); + m_selectType.setId("Type"); + m_autoSelectDrawing.setId("AutoSelectDrawing"); m_snap.setId("Snap"); m_snapSensitivity.addValue(LOW_WSTR); @@ -317,10 +341,14 @@ ControlPointEditorTool::ControlPointEditorTool() void ControlPointEditorTool::updateTranslation() { m_autoSelectDrawing.setQStringName(tr("Auto Select Drawing")); m_snap.setQStringName(tr("Snap")); + m_selectType.setQStringName(tr("Type:")); + m_selectType.setItemUIName(RECTANGULAR_WSTR, tr("Rectangular")); + m_selectType.setItemUIName(FREEHAND_WSTR, tr("Freehand")); + m_snapSensitivity.setQStringName(tr("")); - m_snapSensitivity.setItemUIName(L"Low", tr("Low")); - m_snapSensitivity.setItemUIName(L"Medium", tr("Med")); - m_snapSensitivity.setItemUIName(L"High", tr("High")); + m_snapSensitivity.setItemUIName(LOW_WSTR, tr("Low")); + m_snapSensitivity.setItemUIName(MEDIUM_WSTR, tr("Med")); + m_snapSensitivity.setItemUIName(HIGH_WSTR, tr("High")); } //--------------------------------------------------------------------------- @@ -373,7 +401,7 @@ void ControlPointEditorTool::getNearestStrokeColumnIndexes( void ControlPointEditorTool::drawMovingSegment() { int beforeIndex = m_moveSegmentLimitation.first; int nextIndex = m_moveSegmentLimitation.second; - if (m_action != EDIT_SEGMENT || beforeIndex == -1 || nextIndex == -1 || + if (m_action != SEGMENT_MOVEMENT || beforeIndex == -1 || nextIndex == -1 || !m_moveControlPointEditorStroke.getStroke()) return; tglColor(TPixel::Green); @@ -466,6 +494,12 @@ void ControlPointEditorTool::draw() { color1 = TPixel32:: Black; // TransparencyCheck::instance()->isEnabled()?TPixel32::White:TPixel32::Black; drawRect(m_selectingRect, color1, 0x3F33, true); + } else if (m_action == FREEHAND_SELECTION && !m_track.isEmpty()) { + TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg + ? TPixel32::White + : TPixel32::Black; + tglColor(color); + m_track.drawAllFragments(); } if (m_controlPointEditorStroke.getControlPointCount() <= 0) return; @@ -581,13 +615,18 @@ void ControlPointEditorTool::leftButtonDown(const TPointD &pos, m_action = NONE; m_selection.makeCurrent(); } else { - // ho cliccato lontano da ogni altra curva - m_selectingRect = TRectD(m_pos.x, m_pos.y, m_pos.x + 1, m_pos.y + 1); - if (m_selectingRect.x0 > m_selectingRect.x1) - std::swap(m_selectingRect.x1, m_selectingRect.x0); - if (m_selectingRect.y0 > m_selectingRect.y1) - std::swap(m_selectingRect.y1, m_selectingRect.y0); - m_action = RECT_SELECTION; + if (m_selectType.getValue() == RECTANGULAR_WSTR) { + m_action = RECT_SELECTION; + m_selectingRect = TRectD(m_pos.x, m_pos.y, m_pos.x + 1, m_pos.y + 1); + if (m_selectingRect.x0 > m_selectingRect.x1) + std::swap(m_selectingRect.x1, m_selectingRect.x0); + if (m_selectingRect.y0 > m_selectingRect.y1) + std::swap(m_selectingRect.y1, m_selectingRect.y0); + + } else if (m_selectType.getValue() == FREEHAND_WSTR) { + m_action = FREEHAND_SELECTION; + startFreehand(pos); + } } m_selection.selectNone(); return; @@ -813,12 +852,31 @@ void ControlPointEditorTool::leftButtonDrag(const TPointD &pos, if (m_selectingRect.contains( m_controlPointEditorStroke.getControlPoint(i))) m_selection.select(i); + } else if (m_action == FREEHAND_SELECTION) { + freehandDrag(pos); } invalidate(); } //--------------------------------------------------------------------------- +void ControlPointEditorTool::selectRegion(TStroke *stroke) { + int cpCount = m_controlPointEditorStroke.getControlPointCount(); + + TVectorImage img; + img.addStroke(stroke); + img.findRegions(); + for (int rI = 0; rI < (int)img.getRegionCount(); rI++) { + TRegion *region = img.getRegion(rI); + for (int i = 0; i < cpCount; i++) { + if (region->contains(m_controlPointEditorStroke.getControlPoint(i))) { + m_selection.select(i); + } + } + } +} + +//--------------------------------------------------------------------------- void ControlPointEditorTool::leftButtonUp(const TPointD &realPos, const TMouseEvent &e) { @@ -831,13 +889,19 @@ void ControlPointEditorTool::leftButtonUp(const TPointD &realPos, pos = getSnap(realPos); resetSnap(); - if (m_action == EDIT_SEGMENT) { + if (m_action == SEGMENT_MOVEMENT) { m_moveControlPointEditorStroke.setStroke((TVectorImage *)0, -1); TPointD delta = pos - m_pos; moveSegment(delta, false, e.isShiftPressed()); } - if (m_action == RECT_SELECTION) { + if (m_action == RECT_SELECTION || m_action == FREEHAND_SELECTION) { + if (m_action == FREEHAND_SELECTION) { + closeFreehand(pos); + selectRegion(m_stroke); + m_track.clear(); + } + if (m_selection.isEmpty()) { // Non ho selezionato nulla if (!TTool::getApplication() @@ -961,6 +1025,7 @@ void ControlPointEditorTool::onLeave() { //----------------------------------------------------------------------------- bool ControlPointEditorTool::onPropertyChanged(std::string propertyName) { + CPSelectionType = ::to_string(m_selectType.getValue()); AutoSelectDrawing = (int)(m_autoSelectDrawing.getValue()); Snap = (int)(m_snap.getValue()); SnapSensitivity = (int)(m_snapSensitivity.getIndex()); @@ -982,6 +1047,7 @@ bool ControlPointEditorTool::onPropertyChanged(std::string propertyName) { void ControlPointEditorTool::onActivate() { // TODO: getApplication()->editImageOrSpline(); + m_selectType.setValue(::to_wstring(CPSelectionType.getValue())); m_autoSelectDrawing.setValue(AutoSelectDrawing ? 1 : 0); m_snap.setValue(Snap ? 1 : 0); m_snapSensitivity.setIndex(SnapSensitivity); @@ -1067,3 +1133,28 @@ bool ControlPointEditorTool::isEventAcceptable(QEvent *e) { // TTool *getSplineEditorTool() {return &controlPointEditorTool;} //============================================================================= + +void ControlPointEditorTool::startFreehand(const TPointD &pos) { + m_track.clear(); + m_firstPos = pos; + double pixelSize = getPixelSize(); + m_track.add(TThickPoint(pos, 0), pixelSize * pixelSize); +} + +//----------------------------------------------------------------------------- + +void ControlPointEditorTool::freehandDrag(const TPointD &pos) { + double pixelSize = getPixelSize(); + m_track.add(TThickPoint(pos, 0), pixelSize * pixelSize); +} + +//----------------------------------------------------------------------------- +void ControlPointEditorTool::closeFreehand(const TPointD &pos) { + if (m_track.isEmpty()) return; + double pixelSize = getPixelSize(); + m_track.add(TThickPoint(m_firstPos, 0), pixelSize * pixelSize); + m_track.filterPoints(); + double error = (30.0 / 11) * pixelSize; + m_stroke = m_track.makeStroke(error); + m_stroke->setStyle(1); +}