diff --git a/toonz/sources/tnztools/rasterselectiontool.cpp b/toonz/sources/tnztools/rasterselectiontool.cpp index a5f09c0d..4402c778 100644 --- a/toonz/sources/tnztools/rasterselectiontool.cpp +++ b/toonz/sources/tnztools/rasterselectiontool.cpp @@ -654,6 +654,16 @@ void RasterSelectionTool::leftButtonDrag(const TPointD &pos, tround(std::max(m_firstPos.y, pos.y) - p.y) + p.y); m_selectingRect = rectD; + + if (m_polyline.size() > 1 && m_polyline.hasSymmetryBrushes()) { + m_polyline.clear(); + m_polyline.push_back(m_selectingRect.getP00()); + m_polyline.push_back(m_selectingRect.getP01()); + m_polyline.push_back(m_selectingRect.getP11()); + m_polyline.push_back(m_selectingRect.getP10()); + m_polyline.push_back(m_selectingRect.getP00()); + } + m_bboxs.clear(); TTool::getApplication() @@ -728,16 +738,45 @@ void RasterSelectionTool::leftButtonUp(const TPointD &pos, if (ti || ri) { if (m_strokeSelectionType.getValue() == RECT_SELECTION) { m_bboxs.push_back(m_selectingRect); - m_rasterSelection.select( - TRectD(m_selectingRect.getP00(), m_selectingRect.getP11())); + + if (!m_selectingRect.isEmpty() && m_polyline.hasSymmetryBrushes()) { + // We'll use polyline + m_polyline.clear(); + m_polyline.push_back(m_selectingRect.getP00()); + m_polyline.push_back(m_selectingRect.getP01()); + m_polyline.push_back(m_selectingRect.getP11()); + m_polyline.push_back(m_selectingRect.getP10()); + m_polyline.push_back(m_selectingRect.getP00()); + + std::vector strokes; + for (int i = 0; i < m_polyline.getBrushCount(); i++) + strokes.push_back(m_polyline.makePolylineStroke(i)); + for (int i = 0; i < strokes.size(); i++) + m_rasterSelection.select(*strokes[i]); + } else + m_rasterSelection.select( + TRectD(m_selectingRect.getP00(), m_selectingRect.getP11())); + m_rasterSelection.setFrameId(getCurrentFid()); + m_selectingRect.empty(); + m_polyline.reset(); } else if (m_strokeSelectionType.getValue() == FREEHAND_SELECTION) { closeFreehand(pos); if (m_stroke->getControlPointCount() > 5) { m_rasterSelection.select(*m_stroke); m_rasterSelection.setFrameId(getCurrentFid()); m_rasterSelection.makeCurrent(); + + if (m_track.hasSymmetryBrushes()) { + double error = (30.0 / 11) * sqrt(getPixelSize() * getPixelSize()); + std::vector symmStrokes = + m_track.makeSymmetryStrokes(error); + for (int i = 0; i < symmStrokes.size(); i++) { + symmStrokes[i]->setStyle(m_stroke->getStyle()); + m_rasterSelection.select(*symmStrokes[i]); + } + } } m_track.clear(); } @@ -759,10 +798,19 @@ void RasterSelectionTool::leftButtonDoubleClick(const TPointD &pos, !m_polyline.empty()) { closePolyline(pos); if (m_stroke) { - m_rasterSelection.select(*m_stroke); + if (m_polyline.hasSymmetryBrushes()) { + std::vector strokes; + for (int i = 0; i < m_polyline.getBrushCount(); i++) + strokes.push_back(m_polyline.makePolylineStroke(i)); + for (int i = 0; i < strokes.size(); i++) + m_rasterSelection.select(*strokes[i]); + } else + m_rasterSelection.select(*m_stroke); + m_rasterSelection.setFrameId(getCurrentFid()); m_rasterSelection.makeCurrent(); } + m_polyline.reset(); m_selecting = false; return; } diff --git a/toonz/sources/tnztools/selectiontool.cpp b/toonz/sources/tnztools/selectiontool.cpp index 943485ef..3039c5be 100644 --- a/toonz/sources/tnztools/selectiontool.cpp +++ b/toonz/sources/tnztools/selectiontool.cpp @@ -6,6 +6,7 @@ #include "tcurveutil.h" #include "tenv.h" #include "drawutil.h" +#include "symmetrytool.h" #include "tools/toolhandle.h" #include "tools/cursors.h" #include "toonz/stage2.h" @@ -1100,12 +1101,36 @@ void SelectionTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { delete m_stroke; m_stroke = 0; } + + SymmetryTool *symmetryTool = dynamic_cast( + TTool::getTool("T_Symmetry", TTool::RasterImage)); + TPointD dpiScale = getViewer()->getDpiScale(); + SymmetryObject symmObj = symmetryTool->getSymmetryObject(); + if (m_strokeSelectionType.getValue() == FREEHAND_SELECTION) startFreehand(pos); - if (m_strokeSelectionType.getValue() == POLYLINE_SELECTION) + else if (m_strokeSelectionType.getValue() == POLYLINE_SELECTION) { + if (symmetryTool && symmetryTool->isGuideEnabled() && + !m_polyline.hasSymmetryBrushes()) { + m_polyline.addSymmetryBrushes(symmObj.getLines(), symmObj.getRotation(), + symmObj.getCenterPoint(), + symmObj.isUsingLineSymmetry(), dpiScale); + } + addPointPolyline(pos); - else if (m_polyline.size() != 0) - m_polyline.clear(); + } else { //if (m_polyline.size() != 0) { + // Rectangular selection + if (symmetryTool && symmetryTool->isGuideEnabled()) { + m_selectingRect = TRectD(pos.x, pos.y, pos.x, pos.y); + + // We'll use polyline + m_polyline.reset(); + m_polyline.addSymmetryBrushes(symmObj.getLines(), symmObj.getRotation(), + symmObj.getCenterPoint(), + symmObj.isUsingLineSymmetry(), dpiScale); + m_polyline.setRectangle(m_selectingRect.getP00(), m_selectingRect.getP11()); + } + } } m_firstPos = m_curPos = pos; m_leftButtonMousePressed = true; @@ -1193,24 +1218,21 @@ int SelectionTool::getCursorId() const { void SelectionTool::drawPolylineSelection() { if (m_polyline.empty()) return; - TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg - ? TPixel32::White - : TPixel32::Black; - tglColor(color); - tglDrawCircle(m_polyline[0], 2); - glBegin(GL_LINE_STRIP); - for (UINT i = 0; i < m_polyline.size(); i++) tglVertex(m_polyline[i]); - tglVertex(m_mousePosition); - glEnd(); +// TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg +// ? TPixel32::White +// : TPixel32::Black; + TPixel color = TPixel32::Red; + m_polyline.drawPolyline(m_mousePosition, color); } //----------------------------------------------------------------------------- void SelectionTool::drawFreehandSelection() { if (m_track.isEmpty()) return; - TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg - ? TPixel32::White - : TPixel32::Black; +// TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg +// ? TPixel32::White +// : TPixel32::Black; + TPixel color = TPixel32::Red; tglColor(color); m_track.drawAllFragments(); } @@ -1218,11 +1240,18 @@ void SelectionTool::drawFreehandSelection() { //----------------------------------------------------------------------------- void SelectionTool::drawRectSelection(const TImage *image) { + TPixel color = TPixel32::Red; + + if (!m_polyline.empty()) { + m_polyline.drawRectangle(color); + return; + } + const TVectorImage *vi = dynamic_cast(image); unsigned short stipple = 0x3F33; FourPoints selectingRect = m_selectingRect; if (vi && m_curPos.x >= m_firstPos.x) stipple = 0xFF00; - drawFourPoints(selectingRect, TPixel32::Black, stipple, true); + drawFourPoints(selectingRect, color, stipple, true); } //----------------------------------------------------------------------------- @@ -1324,6 +1353,8 @@ void SelectionTool::onSelectionChanged() { bool SelectionTool::onPropertyChanged(std::string propertyName) { if (propertyName == m_strokeSelectionType.getName()) { SelectionType = ::to_string(m_strokeSelectionType.getValue()); + if (m_strokeSelectionType.getValue() == POLYLINE_SELECTION) + m_polyline.reset(); return true; } return false; @@ -1334,7 +1365,19 @@ bool SelectionTool::onPropertyChanged(std::string propertyName) { //! Viene aggiunto \b pos a \b m_track e disegnato il primo pezzetto del lazzo. //! Viene inizializzato \b m_firstPos void SelectionTool::startFreehand(const TPointD &pos) { - m_track.clear(); + m_track.reset(); + + SymmetryTool *symmetryTool = dynamic_cast( + TTool::getTool("T_Symmetry", TTool::RasterImage)); + TPointD dpiScale = getViewer()->getDpiScale(); + SymmetryObject symmObj = symmetryTool->getSymmetryObject(); + + if (symmetryTool && symmetryTool->isGuideEnabled()) { + m_track.addSymmetryBrushes(symmObj.getLines(), symmObj.getRotation(), + symmObj.getCenterPoint(), + symmObj.isUsingLineSymmetry(), dpiScale); + } + m_firstPos = pos; double pixelSize = getPixelSize(); m_track.add(TThickPoint(pos, 0), pixelSize * pixelSize); @@ -1381,15 +1424,7 @@ void SelectionTool::closePolyline(const TPointD &pos) { if (m_polyline.back() != m_polyline.front()) m_polyline.push_back(m_polyline.front()); - std::vector strokePoints; - for (UINT i = 0; i < m_polyline.size() - 1; i++) { - strokePoints.push_back(TThickPoint(m_polyline[i], 0)); - strokePoints.push_back( - TThickPoint(0.5 * (m_polyline[i] + m_polyline[i + 1]), 0)); - } - strokePoints.push_back(TThickPoint(m_polyline.back(), 0)); - m_polyline.clear(); - m_stroke = new TStroke(strokePoints); + m_stroke = m_polyline.makePolylineStroke(); assert(m_stroke->getPoint(0) == m_stroke->getPoint(1)); invalidate(); } diff --git a/toonz/sources/tnztools/selectiontool.h b/toonz/sources/tnztools/selectiontool.h index 66d458b5..66b237fe 100644 --- a/toonz/sources/tnztools/selectiontool.h +++ b/toonz/sources/tnztools/selectiontool.h @@ -6,7 +6,9 @@ #include "tproperty.h" #include "toonzqt/selection.h" #include "tools/toolutils.h" -#include "toonz/strokegenerator.h" + +#include "symmetrystroke.h" +#include "vectorbrush.h" // For Qt translation support #include @@ -329,8 +331,8 @@ protected: bool m_firstTime; DragSelectionTool::DragTool *m_dragTool; - StrokeGenerator m_track; - std::vector m_polyline; + VectorBrush m_track; + SymmetryStroke m_polyline; TPointD m_mousePosition; TStroke *m_stroke; diff --git a/toonz/sources/tnztools/vectorselectiontool.cpp b/toonz/sources/tnztools/vectorselectiontool.cpp index 2a73d1eb..fb992a30 100644 --- a/toonz/sources/tnztools/vectorselectiontool.cpp +++ b/toonz/sources/tnztools/vectorselectiontool.cpp @@ -1537,8 +1537,10 @@ void VectorSelectionTool::leftButtonDoubleClick(const TPointD &pos, if (m_strokeSelectionType.getIndex() == POLYLINE_SELECTION_IDX && !m_polyline.empty()) { closePolyline(pos); - selectRegionVectorImage(m_includeIntersection.getValue()); + selectRegionVectorImage(m_includeIntersection.getValue(), + m_strokeSelectionType.getIndex()); + m_polyline.reset(); m_selecting = false; invalidate(); @@ -1591,6 +1593,24 @@ void VectorSelectionTool::leftButtonDrag(const TPointD &pos, TRectD rect(m_firstPos, pos); m_selectingRect = rect; + if (m_polyline.size() > 1 && m_polyline.hasSymmetryBrushes()) { + m_polyline.clear(); + m_polyline.push_back(m_selectingRect.getP00()); + m_polyline.push_back(m_selectingRect.getP01()); + m_polyline.push_back(m_selectingRect.getP11()); + m_polyline.push_back(m_selectingRect.getP10()); + m_polyline.push_back(m_selectingRect.getP00()); + + if (!m_shiftPressed) clearSelectedStrokes(); + + m_stroke = m_polyline.makePolylineStroke(0); + selectRegionVectorImage(m_includeIntersection.getValue(), + POLYLINE_SELECTION_IDX); + invalidate(); + m_stroke = 0; + return; + } + std::set oldSelection; if (m_shiftPressed) oldSelection = m_strokeSelection.getSelection(); @@ -1663,15 +1683,18 @@ void VectorSelectionTool::leftButtonUp(const TPointD &pos, TVectorImageP vi = getImage(false); if (vi) { - if (m_strokeSelectionType.getIndex() == RECT_SELECTION_IDX) + if (m_strokeSelectionType.getIndex() == RECT_SELECTION_IDX) { + m_polyline.reset(); + notifySelectionChanged(); - else if (m_strokeSelectionType.getIndex() == FREEHAND_SELECTION_IDX) { + } else if (m_strokeSelectionType.getIndex() == FREEHAND_SELECTION_IDX) { QMutexLocker lock(vi->getMutex()); closeFreehand(pos); if (m_stroke->getControlPointCount() > 3) - selectRegionVectorImage(m_includeIntersection.getValue()); + selectRegionVectorImage(m_includeIntersection.getValue(), + m_strokeSelectionType.getIndex()); delete m_stroke; // >:( m_stroke = 0; @@ -2175,7 +2198,8 @@ void VectorSelectionTool::selectionOutlineStyle(int &capStyle, int &joinStyle) { //----------------------------------------------------------------------------- -void VectorSelectionTool::selectRegionVectorImage(bool includeIntersect) { +void VectorSelectionTool::selectRegionVectorImage(bool includeIntersect, + int selectionIndex) { if (!m_stroke) return; TVectorImageP vi(getImage(false)); @@ -2185,6 +2209,23 @@ void VectorSelectionTool::selectRegionVectorImage(bool includeIntersect) { TVectorImage selectImg; selectImg.addStroke(new TStroke(*m_stroke)); + + std::vector symmStrokes; + if (selectionIndex == POLYLINE_SELECTION_IDX) { + if (m_polyline.size() > 1 && m_polyline.hasSymmetryBrushes()) { + for (int i = 1; i < m_polyline.getBrushCount(); i++) + symmStrokes.push_back(m_polyline.makePolylineStroke(i)); + } + } else if (selectionIndex == FREEHAND_SELECTION_IDX) { + if (m_track.hasSymmetryBrushes()) { + double pixelSize = getPixelSize(); + double error = (30.0 / 11) * pixelSize; + symmStrokes = m_track.makeSymmetryStrokes(error); + } + } + for (int i = 0; i < symmStrokes.size(); i++) + selectImg.addStroke(symmStrokes[i]); + selectImg.findRegions(); int sCount = int(vi->getStrokeCount()), @@ -2208,6 +2249,14 @@ void VectorSelectionTool::selectRegionVectorImage(bool includeIntersect) { if (intersections.size() > 0) { selectionChanged = selectStroke(s, false) || selectionChanged; } + for (int i = 0; i < symmStrokes.size(); i++) { + intersections.clear(); + intersect(symmStrokes[i], currentStroke, intersections, false); + if (intersections.size() > 0) { + selectionChanged = selectStroke(s, false) || selectionChanged; + } + } + } } diff --git a/toonz/sources/tnztools/vectorselectiontool.h b/toonz/sources/tnztools/vectorselectiontool.h index dff9ce37..f1c266ee 100644 --- a/toonz/sources/tnztools/vectorselectiontool.h +++ b/toonz/sources/tnztools/vectorselectiontool.h @@ -385,7 +385,7 @@ private: void doOnActivate() override; void doOnDeactivate() override; - void selectRegionVectorImage(bool includeIntersect); + void selectRegionVectorImage(bool includeIntersect, int selectionIndex); void updateTranslation() override;