Add Symmetry Selection

This commit is contained in:
manongjohn 2023-02-04 21:21:29 -05:00
parent 3d07164fd2
commit 1c8c41fa50
5 changed files with 172 additions and 38 deletions

View file

@ -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);
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<TStroke *> 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<TStroke *> 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) {
if (m_polyline.hasSymmetryBrushes()) {
std::vector<TStroke *> 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;
}

View file

@ -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<SymmetryTool *>(
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<const TVectorImage *>(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<SymmetryTool *>(
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<TThickPoint> 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();
}

View file

@ -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 <QCoreApplication>
@ -329,8 +331,8 @@ protected:
bool m_firstTime;
DragSelectionTool::DragTool *m_dragTool;
StrokeGenerator m_track;
std::vector<TPointD> m_polyline;
VectorBrush m_track;
SymmetryStroke m_polyline;
TPointD m_mousePosition;
TStroke *m_stroke;

View file

@ -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<int> 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<TStroke *> 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;
}
}
}
}

View file

@ -385,7 +385,7 @@ private:
void doOnActivate() override;
void doOnDeactivate() override;
void selectRegionVectorImage(bool includeIntersect);
void selectRegionVectorImage(bool includeIntersect, int selectionIndex);
void updateTranslation() override;