1
2
3 #include "selectiontool.h"
4 #include "rasterselectiontool.h"
5 #include "vectorselectiontool.h"
6 #include "tcurveutil.h"
7 #include "tenv.h"
8 #include "drawutil.h"
9 #include "tools/toolhandle.h"
10 #include "tools/cursors.h"
11 #include "toonz/stage2.h"
12 #include "toonz/tobjecthandle.h"
13
14 #include <QKeyEvent>
15
16 #include <memory>
17
18 using namespace ToolUtils;
19 using namespace DragSelectionTool;
20
21 TEnv::StringVar SelectionType("SelectionType", "Rectangular");
22
23 //-----------------------------------------------------------------------------
24
createNewDragTool(SelectionTool * st,Args...args)25 template <typename Tv, typename Tr, typename... Args> DragSelectionTool::DragTool* createNewDragTool(SelectionTool* st, Args... args) {
26 VectorSelectionTool *vst = dynamic_cast<VectorSelectionTool *>(st);
27 RasterSelectionTool *rst = dynamic_cast<RasterSelectionTool *>(st);
28 if (vst)
29 return new Tv(vst, args...);
30 else if (rst)
31 return new Tr(rst, args...);
32 return nullptr;
33 }
34
createNewMoveSelectionTool(SelectionTool * st)35 DragSelectionTool::DragTool *createNewMoveSelectionTool(SelectionTool *st) {
36 return createNewDragTool<VectorMoveSelectionTool, RasterMoveSelectionTool>(st);
37 }
38
createNewRotationTool(SelectionTool * st)39 DragSelectionTool::DragTool *createNewRotationTool(SelectionTool *st) {
40 return createNewDragTool<VectorRotationTool, RasterRotationTool>(st);
41 }
42
createNewFreeDeformTool(SelectionTool * st)43 DragSelectionTool::DragTool *createNewFreeDeformTool(SelectionTool *st) {
44 return createNewDragTool<VectorFreeDeformTool, RasterFreeDeformTool>(st);
45 }
46
createNewScaleTool(SelectionTool * st,ScaleType type)47 DragSelectionTool::DragTool *createNewScaleTool(SelectionTool *st, ScaleType type) {
48 return createNewDragTool<VectorScaleTool, RasterScaleTool>(st, type);
49 }
50
51 //=============================================================================
52 namespace {
53 //-----------------------------------------------------------------------------
54
55 // Return index of point with min x or y
tminPoint(std::vector<TPointD> points,bool isX)56 int tminPoint(std::vector<TPointD> points, bool isX) {
57 int i;
58 int index = 0;
59 TPointD p = points[0];
60 for (i = 1; i < (int)points.size(); i++) {
61 TPointD nextP = points[i];
62 if ((isX && p.x < nextP.x) || (!isX && p.y < nextP.y)) continue;
63 index = i;
64 }
65 return index;
66 }
67
68 //-----------------------------------------------------------------------------
69
tminPoint(TPointD p0,TPointD p1,bool isX)70 int tminPoint(TPointD p0, TPointD p1, bool isX) {
71 std::vector<TPointD> v;
72 v.push_back(p0);
73 v.push_back(p1);
74 return tminPoint(v, isX);
75 }
76
77 //=============================================================================
78 } // namespace
79 //-----------------------------------------------------------------------------
80
81 //=============================================================================
82 // FourPoints
83 //-----------------------------------------------------------------------------
84
orderedPoints() const85 FourPoints DragSelectionTool::FourPoints::orderedPoints() const {
86 FourPoints newPoints;
87 int i;
88 std::vector<TPointD> allPoints;
89 allPoints.push_back(m_p00);
90 allPoints.push_back(m_p01);
91 allPoints.push_back(m_p10);
92 allPoints.push_back(m_p11);
93 int minXindex1 = tminPoint(allPoints, true);
94 std::vector<TPointD> points;
95 for (i = 0; i < 4; i++)
96 if (i != minXindex1) points.push_back(allPoints[i]);
97 int minXindex2 = tminPoint(points, true);
98
99 int index = tminPoint(allPoints[minXindex1], points[minXindex2], false);
100 TPointD newPoint1 = allPoints[minXindex1];
101 TPointD newPoint2 = points[minXindex2];
102 if (index == 1) std::swap(newPoint1, newPoint2);
103 newPoints.setP00(newPoint1);
104 newPoints.setP01(newPoint2);
105
106 std::vector<TPointD> points2;
107 for (i = 0; i < 3; i++)
108 if (i != minXindex2) points2.push_back(points[i]);
109
110 index = tminPoint(points2, false);
111 newPoints.setP10(points2[index]);
112 newPoints.setP11(points2[(index == 0) ? 1 : 0]);
113 return newPoints;
114 }
115
116 //-----------------------------------------------------------------------------
117
getPoint(int index) const118 TPointD DragSelectionTool::FourPoints::getPoint(int index) const {
119 if (index == 0)
120 return m_p00;
121 else if (index == 1)
122 return m_p10;
123 else if (index == 2)
124 return m_p11;
125 else if (index == 3)
126 return m_p01;
127 else if (index == 4)
128 return (m_p00 + m_p10) * 0.5;
129 else if (index == 5)
130 return (m_p10 + m_p11) * 0.5;
131 else if (index == 6)
132 return (m_p11 + m_p01) * 0.5;
133 else if (index == 7)
134 return (m_p01 + m_p00) * 0.5;
135 return TPointD();
136 }
137
138 //-----------------------------------------------------------------------------
139
setPoint(int index,const TPointD & p)140 void DragSelectionTool::FourPoints::setPoint(int index, const TPointD &p) {
141 if (index == 0)
142 m_p00 = p;
143 else if (index == 1)
144 m_p10 = p;
145 else if (index == 2)
146 m_p11 = p;
147 else if (index == 3)
148 m_p01 = p;
149 }
150
151 //-----------------------------------------------------------------------------
152
enlarge(double d)153 FourPoints DragSelectionTool::FourPoints::enlarge(double d) {
154 TPointD v = normalize(getP10() - getP00());
155 TPointD p00 = getP00() - d * v;
156 TPointD p10 = getP10() + d * v;
157 v = normalize(getP11() - getP10());
158 p10 = p10 - d * v;
159 TPointD p11 = getP11() + d * v;
160 v = normalize(getP01() - getP11());
161 p11 = p11 - d * v;
162 TPointD p01 = getP01() + d * v;
163 v = normalize(getP00() - getP01());
164 p01 = p01 - d * v;
165 p00 = p00 + d * v;
166 return FourPoints(p00, p01, p10, p11);
167 }
168
169 //-----------------------------------------------------------------------------
170
isEmpty()171 bool DragSelectionTool::FourPoints::isEmpty() {
172 return ((getP00().x == getP01().x && getP01().x == getP10().x &&
173 getP10().x == getP11().x) ||
174 (getP00().y == getP01().y && getP01().y == getP10().y &&
175 getP10().y == getP11().y));
176 }
177
178 //-----------------------------------------------------------------------------
179
empty()180 void DragSelectionTool::FourPoints::empty() {
181 m_p00 = TPointD();
182 m_p01 = TPointD();
183 m_p10 = TPointD();
184 m_p11 = TPointD();
185 }
186
187 //-----------------------------------------------------------------------------
188
contains(TPointD p)189 bool DragSelectionTool::FourPoints::contains(TPointD p) {
190 double maxDistance =
191 std::max(tdistance2(getP00(), getP11()), tdistance2(getP10(), getP01()));
192 TPointD outP = p + maxDistance * TPointD(1, 1);
193 TSegment segment(outP, p);
194 std::vector<DoublePair> d;
195 int inters = intersect(TSegment(getP00(), getP10()), segment, d);
196 inters += intersect(TSegment(getP10(), getP11()), segment, d);
197 inters += intersect(TSegment(getP11(), getP01()), segment, d);
198 inters += intersect(TSegment(getP01(), getP00()), segment, d);
199 return inters % 2 == 1;
200 }
201
202 //-----------------------------------------------------------------------------
203
getBox() const204 TRectD DragSelectionTool::FourPoints::getBox() const {
205 double x0 = std::min({getP00().x, getP10().x, getP01().x, getP11().x});
206 double y0 = std::min({getP00().y, getP10().y, getP01().y, getP11().y});
207 double x1 = std::max({getP00().x, getP10().x, getP01().x, getP11().x});
208 double y1 = std::max({getP00().y, getP10().y, getP01().y, getP11().y});
209 return TRectD(TPointD(x0, y0), TPointD(x1, y1));
210 }
211
212 //-----------------------------------------------------------------------------
213
operator =(const TRectD & r)214 FourPoints &DragSelectionTool::FourPoints::operator=(const TRectD &r) {
215 setP00(r.getP00());
216 setP01(r.getP01());
217 setP10(r.getP10());
218 setP11(r.getP11());
219 return *this;
220 }
221
222 //-----------------------------------------------------------------------------
223
operator ==(const FourPoints & p) const224 bool DragSelectionTool::FourPoints::operator==(const FourPoints &p) const {
225 return getP00() == p.getP00() && getP01() == p.getP01() &&
226 getP10() == p.getP10() && getP11() == p.getP11();
227 }
228
229 //-----------------------------------------------------------------------------
230
operator *(const TAffine & aff) const231 FourPoints DragSelectionTool::FourPoints::operator*(const TAffine &aff) const {
232 FourPoints p;
233 p.setP00(aff * getP00());
234 p.setP10(aff * getP10());
235 p.setP11(aff * getP11());
236 p.setP01(aff * getP01());
237 return p;
238 }
239
240 //-----------------------------------------------------------------------------
241
drawFourPoints(const FourPoints & rect,const TPixel32 & color,unsigned short stipple,bool doContrast)242 void DragSelectionTool::drawFourPoints(const FourPoints &rect,
243 const TPixel32 &color,
244 unsigned short stipple,
245 bool doContrast) {
246 GLint src, dst;
247 bool isEnabled;
248 tglColor(color);
249 if (doContrast) {
250 if (color == TPixel32::Black) tglColor(TPixel32(90, 90, 90));
251 isEnabled = glIsEnabled(GL_BLEND);
252 glGetIntegerv(GL_BLEND_SRC, &src);
253 glGetIntegerv(GL_BLEND_DST, &dst);
254 glEnable(GL_BLEND);
255 glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
256 }
257
258 if (stipple != 0xffff) {
259 glLineStipple(1, stipple);
260 glEnable(GL_LINE_STIPPLE);
261 }
262
263 glBegin(GL_LINE_STRIP);
264 tglVertex(rect.getP00());
265 tglVertex(rect.getP01());
266 tglVertex(rect.getP11());
267 tglVertex(rect.getP10());
268 tglVertex(rect.getP00());
269 glEnd();
270 glDisable(GL_LINE_STIPPLE);
271 if (doContrast) {
272 if (!isEnabled) glDisable(GL_BLEND);
273 glBlendFunc(src, dst);
274 }
275 }
276
277 //=============================================================================
278 namespace {
279 //-----------------------------------------------------------------------------
280
281 //=============================================================================
282 // UndoMoveCenter
283 //-----------------------------------------------------------------------------
284
285 class UndoMoveCenter final : public TUndo {
286 SelectionTool *m_tool;
287 TAffine m_aff;
288
289 public:
UndoMoveCenter(SelectionTool * tool,const TAffine & aff)290 UndoMoveCenter(SelectionTool *tool, const TAffine &aff)
291 : m_tool(tool), m_aff(aff) {}
~UndoMoveCenter()292 ~UndoMoveCenter() {}
undo() const293 void undo() const override {
294 m_tool->setCenter(m_aff.inv() * m_tool->getCenter());
295 m_tool->invalidate();
296 }
redo() const297 void redo() const override {
298 m_tool->setCenter(m_aff * m_tool->getCenter());
299 m_tool->invalidate();
300 }
getSize() const301 int getSize() const override { return sizeof(*this) + sizeof(*m_tool); }
302
getHistoryString()303 QString getHistoryString() override { return QObject::tr("Move Center"); }
304 };
305
306 //=============================================================================
307 // MoveCenterTool
308 //-----------------------------------------------------------------------------
309
310 class MoveCenterTool final : public DragTool {
311 TPointD m_startPos;
312 TAffine m_transform;
313
314 public:
MoveCenterTool(SelectionTool * tool)315 MoveCenterTool(SelectionTool *tool)
316 : DragTool(tool), m_startPos(), m_transform() {}
translateCenter(TAffine aff)317 void translateCenter(TAffine aff) {
318 getTool()->setCenter(aff * getTool()->getCenter());
319 m_transform *= aff;
320 getTool()->invalidate();
321 }
leftButtonDown(const TPointD & pos,const TMouseEvent & e)322 void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override {
323 m_startPos = pos;
324 }
leftButtonDrag(const TPointD & pos,const TMouseEvent & e)325 void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override {
326 TPointD delta = pos - m_startPos;
327 FourPoints bbox = getTool()->getBBox();
328 TPointD bboxCenter = 0.5 * (bbox.getP11() + bbox.getP00());
329 double maxDistance2 =
330 32 * getTool()->getPixelSize() * getTool()->getPixelSize();
331 TAffine aff = m_transform.inv() * TTranslation(delta);
332 TPointD newCenter = aff * getTool()->getCenter();
333 if (tdistance2(newCenter, bboxCenter) < maxDistance2)
334 translateCenter(TTranslation(bboxCenter - getTool()->getCenter()));
335 else
336 translateCenter(aff);
337 }
leftButtonUp(const TPointD & pos,const TMouseEvent & e)338 void leftButtonUp(const TPointD &pos, const TMouseEvent &e) override {
339 UndoMoveCenter *undo = new UndoMoveCenter(getTool(), m_transform);
340 TUndoManager::manager()->add(undo);
341 }
draw()342 void draw() override {}
343 };
344
345 //=============================================================================
346 } // namespace
347 //-----------------------------------------------------------------------------
348
349 //=============================================================================
350 // DeformTool
351 //-----------------------------------------------------------------------------
352
DeformTool(SelectionTool * tool)353 DragSelectionTool::DeformTool::DeformTool(SelectionTool *tool)
354 : DragTool(tool)
355 , m_curPos()
356 , m_isDragging(false)
357 , m_startScaleValue(tool->m_deformValues.m_scaleValue) {}
358
359 //-----------------------------------------------------------------------------
360
getSymmetricPointIndex(int index) const361 int DragSelectionTool::DeformTool::getSymmetricPointIndex(int index) const {
362 if (index == 0 || index == 4 || index == 1 || index == 5) return index + 2;
363 return index - 2;
364 }
365
366 //-----------------------------------------------------------------------------
367
getBeforePointIndex(int index) const368 int DragSelectionTool::DeformTool::getBeforePointIndex(int index) const {
369 if (index < 4) return (index == 0) ? 7 : index + 3;
370 return index - 4;
371 }
372
373 //-----------------------------------------------------------------------------
374
getNextPointIndex(int index) const375 int DragSelectionTool::DeformTool::getNextPointIndex(int index) const {
376 if (index < 4) return index + 4;
377 return (index == 7) ? 0 : index - 3;
378 }
379
380 //-----------------------------------------------------------------------------
381
getBeforeVertexIndex(int index) const382 int DragSelectionTool::DeformTool::getBeforeVertexIndex(int index) const {
383 if (index < 4) return (index == 0) ? 3 : index - 1;
384 return index - 4;
385 }
386
387 //-----------------------------------------------------------------------------
388
getNextVertexIndex(int index) const389 int DragSelectionTool::DeformTool::getNextVertexIndex(int index) const {
390 if (index < 4) return (index == 3) ? 0 : index + 1;
391 return (index == 7) ? 0 : index - 3;
392 }
393
394 //-----------------------------------------------------------------------------
395
leftButtonDown(const TPointD & pos,const TMouseEvent & e)396 void DragSelectionTool::DeformTool::leftButtonDown(const TPointD &pos,
397 const TMouseEvent &e) {
398 m_isDragging = true;
399 m_curPos = pos;
400 setStartPos(pos);
401 }
402
403 //-----------------------------------------------------------------------------
404
leftButtonUp(const TPointD & pos,const TMouseEvent & e)405 void DragSelectionTool::DeformTool::leftButtonUp(const TPointD &pos,
406 const TMouseEvent &e) {
407 addTransformUndo();
408 m_isDragging = false;
409 }
410
411 //=============================================================================
412 // Rotation
413 //-----------------------------------------------------------------------------
414
Rotation(DeformTool * deformTool)415 DragSelectionTool::Rotation::Rotation(DeformTool *deformTool)
416 : m_curAng(), m_dstAng(), m_deformTool(deformTool) {}
417
418 //-----------------------------------------------------------------------------
419
getStartCenter() const420 TPointD DragSelectionTool::Rotation::getStartCenter() const {
421 return m_deformTool->getTool()->getCenter();
422 }
423
424 //-----------------------------------------------------------------------------
425
leftButtonDrag(const TPointD & pos,const TMouseEvent & e)426 void DragSelectionTool::Rotation::leftButtonDrag(const TPointD &pos,
427 const TMouseEvent &e) {
428 SelectionTool *tool = m_deformTool->getTool();
429 TPointD center = tool->getCenter();
430 TPointD curPos = m_deformTool->getCurPos();
431 TPointD delta = pos - curPos;
432 TPointD a = pos - center;
433 TPointD b = (pos - delta) - center;
434 double a2 = norm2(a);
435 double b2 = norm2(b);
436 const double epsilon = 1e-8;
437 double dang = 0;
438 double scale = 1;
439 if (a2 <= epsilon || b2 <= epsilon) return;
440 dang = asin(cross(a, b) / sqrt(a2 * b2)) * -M_180_PI;
441 if (e.isShiftPressed()) {
442 m_dstAng += dang;
443 double ang = tfloor((int)(m_dstAng + 22.5), 45);
444 dang = ang - m_curAng;
445 m_curAng = ang;
446 } else {
447 m_dstAng += dang;
448 dang = m_dstAng - m_curAng;
449 m_curAng = m_dstAng;
450 }
451
452 tool->m_deformValues.m_rotationAngle =
453 tool->m_deformValues.m_rotationAngle + dang;
454 m_deformTool->transform(TRotation(center, dang), dang);
455 m_deformTool->setCurPos(pos);
456 TTool::getApplication()->getCurrentTool()->notifyToolChanged();
457 }
458
459 //-----------------------------------------------------------------------------
460
draw()461 void DragSelectionTool::Rotation::draw() {
462 tglDrawSegment(m_deformTool->getCurPos(),
463 m_deformTool->getTool()->getCenter());
464 }
465
466 //=============================================================================
467 // FreeDeform
468 //-----------------------------------------------------------------------------
469
FreeDeform(DeformTool * deformTool)470 DragSelectionTool::FreeDeform::FreeDeform(DeformTool *deformTool)
471 : m_deformTool(deformTool) {}
472
473 //-----------------------------------------------------------------------------
474
leftButtonDrag(const TPointD & pos,const TMouseEvent & e)475 void DragSelectionTool::FreeDeform::leftButtonDrag(const TPointD &pos,
476 const TMouseEvent &e) {
477 SelectionTool *tool = m_deformTool->getTool();
478 TPointD delta = pos - m_deformTool->getCurPos();
479 TPointD center = tool->getCenter();
480 int index = tool->getSelectedPoint();
481 FourPoints bbox = tool->getBBox();
482 FourPoints newBbox = bbox;
483 if (index < 4)
484 bbox.setPoint(index, bbox.getPoint(index) + delta);
485 else {
486 int beforeIndex = m_deformTool->getBeforeVertexIndex(index);
487 bbox.setPoint(beforeIndex, bbox.getPoint(beforeIndex) + delta);
488 bbox.setPoint(index, bbox.getPoint(index) + delta);
489 int nextIndex = m_deformTool->getNextVertexIndex(index);
490 bbox.setPoint(nextIndex, bbox.getPoint(nextIndex) + delta);
491 }
492 tool->setBBox(bbox);
493 m_deformTool->setCurPos(pos);
494 m_deformTool->applyTransform(bbox);
495 }
496
497 //=============================================================================
498 // MoveSelection
499 //-----------------------------------------------------------------------------
500
MoveSelection(DeformTool * deformTool)501 DragSelectionTool::MoveSelection::MoveSelection(DeformTool *deformTool)
502 : m_deformTool(deformTool), m_lastDelta(), m_firstPos() {}
503
504 //-----------------------------------------------------------------------------
505
leftButtonDown(const TPointD & pos,const TMouseEvent & e)506 void DragSelectionTool::MoveSelection::leftButtonDown(const TPointD &pos,
507 const TMouseEvent &e) {
508 m_deformTool->setCurPos(pos);
509 m_firstPos = pos;
510 }
511
512 //-----------------------------------------------------------------------------
513
leftButtonDrag(const TPointD & pos,const TMouseEvent & e)514 void DragSelectionTool::MoveSelection::leftButtonDrag(const TPointD &pos,
515 const TMouseEvent &e) {
516 TAffine aff;
517 TPointD curPos = m_deformTool->getCurPos();
518 TPointD delta = pos - curPos;
519 if (e.isShiftPressed()) {
520 if (m_lastDelta == TPointD()) {
521 TPointD totalDelta = curPos - m_firstPos;
522 aff = TTranslation(totalDelta).inv();
523 } else
524 aff = TTranslation(m_lastDelta).inv();
525 if (fabs((curPos - m_firstPos).x) > fabs((curPos - m_firstPos).y))
526 m_lastDelta = TPointD((curPos - m_firstPos).x, 0);
527 else
528 m_lastDelta = TPointD(0, (curPos - m_firstPos).y);
529 aff *= TTranslation(m_lastDelta);
530 } else
531 aff = TTranslation(delta);
532 double factor = 1.0 / Stage::inch;
533 m_deformTool->getTool()->m_deformValues.m_moveValue =
534 m_deformTool->getTool()->m_deformValues.m_moveValue + factor * delta;
535 m_deformTool->transform(aff);
536 m_deformTool->setCurPos(pos);
537 TTool::getApplication()->getCurrentTool()->notifyToolChanged();
538 }
539
540 //=============================================================================
541 // Scale
542 //-----------------------------------------------------------------------------
543
Scale(DeformTool * deformTool,ScaleType type)544 DragSelectionTool::Scale::Scale(DeformTool *deformTool, ScaleType type)
545 : m_deformTool(deformTool)
546 , m_startCenter(deformTool->getTool()->getCenter())
547 , m_type(type)
548 , m_isShiftPressed(false)
549 , m_isAltPressed(false)
550 , m_scaleInCenter(true) {
551 int i;
552 for (i = 0; i < (int)m_deformTool->getTool()->getBBoxsCount(); i++)
553 m_startBboxs.push_back(m_deformTool->getTool()->getBBox(i));
554 }
555
556 //-----------------------------------------------------------------------------
557
getIntersectionPoint(const TPointD & point0,const TPointD & point1,const TPointD & point2,const TPointD & point3,const TPointD & p) const558 TPointD DragSelectionTool::Scale::getIntersectionPoint(const TPointD &point0,
559 const TPointD &point1,
560 const TPointD &point2,
561 const TPointD &point3,
562 const TPointD &p) const {
563 // Parametri della retta passante per point0, point1
564 double d1x = point0.x - point1.x;
565 double m1 = d1x == 0 ? 0 : (point0.y - point1.y) / d1x;
566 double q1 = point1.y - m1 * point1.x;
567 // Parametri della retta passante per p parallela alla retta passante per
568 // point1, point2
569 double d2x = point2.x - point3.x;
570 double m2 = d2x == 0 ? 0 : (point2.y - point3.y) / d2x;
571 double q2 = p.y - m2 * p.x;
572 // Calcolo l'intersezione tra le due rette
573 double x, y, m, q;
574 if (d1x == 0) {
575 x = point0.x;
576 m = m2;
577 q = q2;
578 } else if (d2x == 0) {
579 x = p.x;
580 m = m1;
581 q = q1;
582 } else {
583 assert(m1 != m2);
584 x = (q1 - q2) / (m2 - m1);
585 m = m1;
586 q = q1;
587 }
588 y = m * x + q;
589 return TPointD(x, y);
590 }
591
592 //-----------------------------------------------------------------------------
593
bboxScale(int index,const FourPoints & oldBbox,const TPointD & pos)594 DragSelectionTool::FourPoints DragSelectionTool::Scale::bboxScale(
595 int index, const FourPoints &oldBbox, const TPointD &pos) {
596 FourPoints bbox = oldBbox;
597 TPointD p = oldBbox.getPoint(index);
598 int nextIndex = m_deformTool->getNextVertexIndex(index);
599 TPointD nextP = oldBbox.getPoint(nextIndex);
600 int nextIndex2 = m_deformTool->getNextVertexIndex(nextIndex);
601 TPointD next2P = oldBbox.getPoint(nextIndex2);
602 TPointD newP = getIntersectionPoint(next2P, nextP, nextP, p, pos);
603 bbox.setPoint(nextIndex, newP);
604
605 int beforeIndex = m_deformTool->getBeforeVertexIndex(index);
606 TPointD beforeP = oldBbox.getPoint(beforeIndex);
607 int before2Index = m_deformTool->getBeforeVertexIndex(beforeIndex);
608 TPointD before2P = oldBbox.getPoint(before2Index);
609 newP = getIntersectionPoint(before2P, beforeP, beforeP, p, pos);
610 bbox.setPoint(beforeIndex, newP);
611
612 if (index < 4) bbox.setPoint(index, pos);
613
614 return bbox;
615 }
616
617 //-----------------------------------------------------------------------------
618
computeScaleValue(int movedIndex,const FourPoints newBbox)619 TPointD DragSelectionTool::Scale::computeScaleValue(int movedIndex,
620 const FourPoints newBbox) {
621 TPointD p = m_startBboxs[0].getPoint(movedIndex);
622 if (movedIndex < 4) {
623 int beforeIndex = m_deformTool->getBeforePointIndex(movedIndex);
624 int nextIndex = m_deformTool->getNextPointIndex(movedIndex);
625 FourPoints bbox = bboxScale(nextIndex, newBbox, p);
626 TPointD scale1 = computeScaleValue(beforeIndex, bbox);
627 bbox = bboxScale(beforeIndex, newBbox, p);
628 TPointD scale2 = computeScaleValue(nextIndex, bbox);
629 if (movedIndex % 2 == 0)
630 return TPointD(scale1.x, scale2.y);
631 else
632 return TPointD(scale2.x, scale1.y);
633 }
634 int symmetricIndex = m_deformTool->getSymmetricPointIndex(movedIndex);
635 TPointD s = m_startBboxs[0].getPoint(symmetricIndex);
636 TPointD center = m_scaleInCenter ? m_startCenter : s;
637 TPointD nearP =
638 m_startBboxs[0].getPoint(m_deformTool->getBeforePointIndex(movedIndex));
639 TPointD pc = getIntersectionPoint(nearP, p, p, s, center);
640 TPointD newp = newBbox.getPoint(movedIndex);
641 TPointD news = newBbox.getPoint(symmetricIndex);
642 TPointD newNearP =
643 newBbox.getPoint(m_deformTool->getBeforePointIndex(movedIndex));
644 TPointD newpc = getIntersectionPoint(newNearP, newp, newp, news, center);
645
646 double newD = tdistance2(newpc, center);
647 double oldD = tdistance2(pc, center);
648 double f = sqrt(newD / oldD) - 1;
649 TPointD startScaleValue = m_deformTool->getStartScaleValue();
650 if (movedIndex % 2 == 1) {
651 double sign = (pc.x < center.x && newpc.x < center.x) ||
652 (pc.x > center.x && newpc.x > center.x)
653 ? 1
654 : -1;
655 double x =
656 startScaleValue.x == 0 ? f : startScaleValue.x + startScaleValue.x * f;
657 return TPointD(sign * x, startScaleValue.y);
658 } else {
659 double sign = (pc.y < center.y && newpc.y < center.y) ||
660 (pc.y > center.y && newpc.y > center.y)
661 ? 1
662 : -1;
663 double y =
664 startScaleValue.y == 0 ? f : startScaleValue.y + startScaleValue.y * f;
665 return TPointD(startScaleValue.x, sign * y);
666 }
667 }
668
669 //-----------------------------------------------------------------------------
670
getScaledPoint(int index,const FourPoints & oldBbox,const TPointD scaleValue,const TPointD center)671 TPointD DragSelectionTool::Scale::getScaledPoint(int index,
672 const FourPoints &oldBbox,
673 const TPointD scaleValue,
674 const TPointD center) {
675 TPointD p = oldBbox.getPoint(index);
676 int symmetricIndex = m_deformTool->getSymmetricPointIndex(index);
677 TPointD s = oldBbox.getPoint(symmetricIndex);
678 if (index < 4) {
679 int beforeIndex = m_deformTool->getBeforePointIndex(index);
680 int nextIndex = m_deformTool->getNextPointIndex(index);
681 TPointD newbp = getScaledPoint(beforeIndex, oldBbox, scaleValue, center);
682 TPointD newnp = getScaledPoint(nextIndex, oldBbox, scaleValue, center);
683 TPointD bp = oldBbox.getPoint(m_deformTool->getBeforePointIndex(index));
684 TPointD np = oldBbox.getPoint(m_deformTool->getNextPointIndex(index));
685 TPointD in = getIntersectionPoint(np, p, bp, p, newbp);
686 return getIntersectionPoint(newbp, in, np, p, newnp);
687 }
688 TPointD nearP = oldBbox.getPoint(m_deformTool->getBeforePointIndex(index));
689 TPointD nearS =
690 oldBbox.getPoint(m_deformTool->getBeforePointIndex(symmetricIndex));
691 TPointD pc = getIntersectionPoint(nearP, p, p, s, center);
692 TPointD sc = getIntersectionPoint(nearS, s, p, s, center);
693 if (center == pc) return pc;
694 TPointD v = normalize(center - pc);
695 double currentD = tdistance(sc, pc);
696 double startD = (index % 2 == 1)
697 ? currentD / m_deformTool->getStartScaleValue().x
698 : currentD / m_deformTool->getStartScaleValue().y;
699 double factor = (index % 2 == 1) ? scaleValue.x : scaleValue.y;
700 double d = (currentD - startD * factor) * tdistance(center, pc) / currentD;
701 return TPointD(pc.x + d * v.x, pc.y + d * v.y);
702 }
703
704 //-----------------------------------------------------------------------------
705
getNewCenter(int index,const FourPoints bbox,const TPointD scaleValue)706 TPointD DragSelectionTool::Scale::getNewCenter(int index, const FourPoints bbox,
707 const TPointD scaleValue) {
708 int xIndex, yIndex;
709 if (index < 4) {
710 xIndex = m_deformTool->getBeforePointIndex(index);
711 yIndex = m_deformTool->getNextPointIndex(index);
712 } else {
713 xIndex =
714 m_deformTool->getNextPointIndex(m_deformTool->getNextPointIndex(index));
715 yIndex = index;
716 }
717 if (index % 2 == 1) std::swap(xIndex, yIndex);
718 FourPoints xBbox = bboxScale(xIndex, bbox, m_startCenter);
719 TPointD xCenter = getScaledPoint(
720 xIndex, xBbox, scaleValue,
721 xBbox.getPoint(m_deformTool->getSymmetricPointIndex(xIndex)));
722 FourPoints yBbox = bboxScale(yIndex, bbox, m_startCenter);
723 TPointD yCenter = getScaledPoint(
724 yIndex, yBbox, scaleValue,
725 yBbox.getPoint(m_deformTool->getSymmetricPointIndex(yIndex)));
726 TPointD in = getIntersectionPoint(bbox.getP00(), bbox.getP10(), bbox.getP10(),
727 bbox.getP11(), xCenter);
728 return getIntersectionPoint(in, xCenter, bbox.getP00(), bbox.getP10(),
729 yCenter);
730 }
731
732 //-----------------------------------------------------------------------------
733
bboxScaleInCenter(int index,const FourPoints & oldBbox,const TPointD newPos,TPointD & scaleValue,const TPointD center,bool recomputeScaleValue)734 FourPoints DragSelectionTool::Scale::bboxScaleInCenter(
735 int index, const FourPoints &oldBbox, const TPointD newPos,
736 TPointD &scaleValue, const TPointD center, bool recomputeScaleValue) {
737 TPointD oldp = oldBbox.getPoint(index);
738 if (areAlmostEqual(oldp.x, newPos.x, 1e-2) &&
739 areAlmostEqual(oldp.y, newPos.y, 1e-2))
740 return oldBbox;
741 FourPoints bbox = bboxScale(index, oldBbox, newPos);
742 if (recomputeScaleValue) scaleValue = computeScaleValue(index, bbox);
743 if (!m_scaleInCenter) return bbox;
744 int symmetricIndex = m_deformTool->getSymmetricPointIndex(index);
745 // Gestisco il caso particolare in cui uno dei fattori di scalatura e' -100% e
746 // center e' al centro della bbox
747 if (bbox.getPoint(index) == oldBbox.getPoint(symmetricIndex)) {
748 bbox.setPoint(symmetricIndex, oldBbox.getPoint(index));
749 bbox.setPoint(m_deformTool->getNextPointIndex(symmetricIndex),
750 oldBbox.getPoint(m_deformTool->getBeforePointIndex(index)));
751 bbox.setPoint(m_deformTool->getBeforePointIndex(symmetricIndex),
752 oldBbox.getPoint(m_deformTool->getNextPointIndex(index)));
753 } else
754 bbox =
755 bboxScale(symmetricIndex, bbox,
756 getScaledPoint(symmetricIndex, oldBbox, scaleValue, center));
757 return bbox;
758 }
759
760 //-----------------------------------------------------------------------------
761
leftButtonDown(const TPointD & pos,const TMouseEvent & e)762 void DragSelectionTool::Scale::leftButtonDown(const TPointD &pos,
763 const TMouseEvent &e) {
764 m_isShiftPressed = e.isShiftPressed();
765 m_isAltPressed = e.isAltPressed();
766 }
767
768 //-----------------------------------------------------------------------------
769
leftButtonDrag(const TPointD & pos,const TMouseEvent & e)770 void DragSelectionTool::Scale::leftButtonDrag(const TPointD &pos,
771 const TMouseEvent &e) {
772 SelectionTool *tool = m_deformTool->getTool();
773 bool isBboxReset = false;
774 if (m_isShiftPressed != e.isShiftPressed() ||
775 m_isAltPressed != e.isAltPressed()) {
776 m_deformTool->applyTransform(m_startBboxs[0]);
777 tool->setBBox(m_startBboxs[0]);
778 tool->setCenter(m_startCenter);
779 isBboxReset = true;
780 m_isShiftPressed = e.isShiftPressed();
781 m_isAltPressed = e.isAltPressed();
782 }
783 TPointD newPos = pos;
784 int selectedIndex = tool->getSelectedPoint();
785 if (m_isShiftPressed && m_type == ScaleType::GLOBAL) {
786 TPointD point = tool->getBBox().getPoint(selectedIndex);
787 TPointD delta;
788 if (!isBboxReset)
789 delta = pos - m_deformTool->getCurPos();
790 else
791 delta = pos - m_deformTool->getStartPos();
792 int symmetricIndex = m_deformTool->getSymmetricPointIndex(selectedIndex);
793 TPointD symmetricPoint = tool->getBBox().getPoint(symmetricIndex);
794 TPointD v = normalize(point - symmetricPoint);
795 delta = v * (v * delta);
796 newPos = point + delta;
797 }
798 m_scaleInCenter = m_isAltPressed;
799 m_deformTool->setCurPos(pos);
800 TPointD scaleValue = m_deformTool->transform(selectedIndex, newPos);
801 tool->m_deformValues.m_scaleValue = scaleValue;
802 TTool::getApplication()->getCurrentTool()->notifyToolChanged();
803 }
804
805 //=============================================================================
806 // SelectionTool
807 //-----------------------------------------------------------------------------
808
SelectionTool(int targetType)809 SelectionTool::SelectionTool(int targetType)
810 : TTool("T_Selection")
811 , m_firstTime(true)
812 , m_dragTool(0)
813 , m_what(Outside)
814 , m_leftButtonMousePressed(false)
815 , m_shiftPressed(false)
816 , m_selecting(false)
817 , m_mousePosition(TPointD())
818 , m_stroke(0)
819 , m_justSelected(false)
820 , m_strokeSelectionType("Type:")
821 , m_deformValues()
822 , m_cursorId(ToolCursor::CURSOR_ARROW) {
823 bind(targetType);
824 m_prop.bind(m_strokeSelectionType);
825
826 m_strokeSelectionType.addValue(RECT_SELECTION);
827 m_strokeSelectionType.addValue(FREEHAND_SELECTION);
828 m_strokeSelectionType.addValue(POLYLINE_SELECTION);
829 m_strokeSelectionType.setId("Type");
830 }
831
832 //-----------------------------------------------------------------------------
833
~SelectionTool()834 SelectionTool::~SelectionTool() {
835 delete m_dragTool;
836 if (m_stroke) {
837 delete m_stroke;
838 m_stroke = 0;
839 }
840 if (!m_freeDeformers.empty()) clearPointerContainer(m_freeDeformers);
841 }
842
843 //-----------------------------------------------------------------------------
844
clearDeformers()845 void SelectionTool::clearDeformers() { clearPointerContainer(m_freeDeformers); }
846
847 //-----------------------------------------------------------------------------
848
getCenter(int index) const849 TPointD SelectionTool::getCenter(int index) const {
850 if (m_centers.empty()) return TPointD();
851 assert((int)m_centers.size() > index);
852 return m_centers[index];
853 }
854
855 //-----------------------------------------------------------------------------
856
setCenter(const TPointD & center,int index)857 void SelectionTool::setCenter(const TPointD ¢er, int index) {
858 if (m_centers.empty()) return;
859 assert((int)m_centers.size() > index);
860 m_centers[index] = center;
861 }
862
863 //-----------------------------------------------------------------------------
864
getBBoxsCount() const865 int SelectionTool::getBBoxsCount() const { return m_bboxs.size(); }
866
867 //-----------------------------------------------------------------------------
868
getBBox(int index) const869 DragSelectionTool::FourPoints SelectionTool::getBBox(int index) const {
870 if (m_bboxs.empty()) return DragSelectionTool::FourPoints();
871 assert((int)m_bboxs.size() > index);
872 return m_bboxs[index];
873 }
874
875 //-----------------------------------------------------------------------------
876
setBBox(const DragSelectionTool::FourPoints & points,int index)877 void SelectionTool::setBBox(const DragSelectionTool::FourPoints &points,
878 int index) {
879 if (m_bboxs.empty()) return;
880 assert((int)m_bboxs.size() > index);
881 m_bboxs[index] = points;
882 }
883
884 //-----------------------------------------------------------------------------
885
getFreeDeformer(int index) const886 FreeDeformer *SelectionTool::getFreeDeformer(int index) const {
887 if (m_freeDeformers.empty()) return 0;
888 return m_freeDeformers[index];
889 }
890
891 //-----------------------------------------------------------------------------
892
updateTranslation()893 void SelectionTool::updateTranslation() {
894 m_strokeSelectionType.setQStringName(tr("Type:"));
895 m_strokeSelectionType.setItemUIName(RECT_SELECTION, tr("Rectangular"));
896 m_strokeSelectionType.setItemUIName(FREEHAND_SELECTION, tr("Freehand"));
897 m_strokeSelectionType.setItemUIName(POLYLINE_SELECTION, tr("Polyline"));
898 }
899 //-----------------------------------------------------------------------------
900
updateAction(TPointD pos,const TMouseEvent & e)901 void SelectionTool::updateAction(TPointD pos, const TMouseEvent &e) {
902 TImageP image = getImage(false);
903 TToonzImageP ti = image;
904 TRasterImageP ri = image;
905 TVectorImageP vi = image;
906
907 m_what = Outside;
908 m_cursorId = ToolCursor::StrokeSelectCursor;
909
910 if (!ti && !vi && !ri) return;
911
912 bool shift = e.isShiftPressed();
913
914 if (shift && !m_leftButtonMousePressed && isModifiableSelectionType()) {
915 m_what = ADD_SELECTION;
916 m_cursorId = ToolCursor::SplineEditorCursorAdd;
917 } else if (m_leftButtonMousePressed)
918 return;
919
920 if (!isSelectionEditable()) return;
921
922 FourPoints bbox = getBBox();
923
924 double pixelSize = getPixelSize();
925 if (!bbox.isEmpty()) {
926 double maxDist = 17 * pixelSize;
927 double maxDist2 = maxDist * maxDist;
928 double p = (15 * pixelSize);
929 m_selectedPoint = NONE;
930 if (tdistance2(bbox.getP00(), pos) < maxDist2 + p)
931 m_selectedPoint = P00;
932 else if (tdistance2(bbox.getP11(), pos) < maxDist2 + p)
933 m_selectedPoint = P11;
934 else if (tdistance2(bbox.getP01(), pos) < maxDist2 + p)
935 m_selectedPoint = P01;
936 else if (tdistance2(bbox.getP10(), pos) < maxDist2 + p)
937 m_selectedPoint = P10;
938
939 if (tdistance2(bbox.getBottomLeft() + TPointD(-p, -p), pos) < maxDist2) {
940 m_what = ROTATION;
941 m_cursorId = ToolCursor::RotBottomLeft;
942 return;
943 } else if (tdistance2(bbox.getBottomRight() + TPointD(p, -p), pos) <
944 maxDist2) {
945 m_what = ROTATION;
946 m_cursorId = ToolCursor::RotBottomRight;
947 return;
948 } else if (tdistance2(bbox.getTopRight() + TPointD(p, p), pos) < maxDist2) {
949 m_what = ROTATION;
950 m_cursorId = ToolCursor::RotCursor;
951 return;
952 } else if (tdistance2(bbox.getTopLeft() + TPointD(-p, p), pos) < maxDist2) {
953 m_what = ROTATION;
954 m_cursorId = ToolCursor::RotTopLeft;
955 return;
956 }
957 maxDist = 5 * pixelSize;
958 maxDist2 = maxDist * maxDist;
959 if (!isLevelType() && !isSelectedFramesType() &&
960 tdistance2(getCenter(), pos) < maxDist2) {
961 m_what = MOVE_CENTER;
962 m_cursorId = ToolCursor::PointingHandCursor;
963 return;
964 }
965 if (tdistance2(bbox.getP00(), pos) < maxDist2 ||
966 tdistance2(bbox.getP11(), pos) < maxDist2 ||
967 tdistance2(bbox.getP01(), pos) < maxDist2 ||
968 tdistance2(bbox.getP10(), pos) < maxDist2) {
969 if (!e.isCtrlPressed() || isLevelType() || isSelectedFramesType()) {
970 m_what = SCALE;
971 if (tdistance2(bbox.getTopRight(), pos) < maxDist2 ||
972 tdistance2(bbox.getBottomLeft(), pos) < maxDist2)
973 m_cursorId = ToolCursor::ScaleCursor;
974 else
975 m_cursorId = ToolCursor::ScaleInvCursor;
976 } else {
977 m_cursorId = ToolCursor::DistortCursor;
978 m_what = DEFORM;
979 }
980 return;
981 }
982 if (isCloseToSegment(pos, TSegment(bbox.getPoint(0), bbox.getPoint(3)),
983 maxDist))
984 m_selectedPoint = P0M;
985 else if (isCloseToSegment(pos, TSegment(bbox.getPoint(1), bbox.getPoint(2)),
986 maxDist))
987 m_selectedPoint = P1M;
988 else if (isCloseToSegment(pos, TSegment(bbox.getPoint(3), bbox.getPoint(2)),
989 maxDist))
990 m_selectedPoint = PM1;
991 else if (isCloseToSegment(pos, TSegment(bbox.getPoint(0), bbox.getPoint(1)),
992 maxDist))
993 m_selectedPoint = PM0;
994 if (m_selectedPoint == P0M || m_selectedPoint == P1M) {
995 if (!e.isCtrlPressed() || isLevelType() || isSelectedFramesType()) {
996 m_cursorId = ToolCursor::ScaleHCursor;
997 m_what = SCALE_X;
998 } else {
999 m_cursorId = ToolCursor::DistortCursor;
1000 m_what = DEFORM;
1001 }
1002 return;
1003 }
1004 if (m_selectedPoint == PM1 || m_selectedPoint == PM0) {
1005 if (!e.isCtrlPressed() || isLevelType() || isSelectedFramesType()) {
1006 m_cursorId = ToolCursor::ScaleVCursor;
1007 m_what = SCALE_Y;
1008 } else {
1009 m_cursorId = ToolCursor::DistortCursor;
1010 m_what = DEFORM;
1011 }
1012 return;
1013 }
1014 TPointD hpos = bbox.getP10() - TPointD(14 * pixelSize, 15 * pixelSize);
1015 TRectD rect(hpos - TPointD(14 * pixelSize, 5 * pixelSize),
1016 hpos + TPointD(14 * pixelSize, 5 * pixelSize));
1017 if (!m_deformValues.m_isSelectionModified && rect.contains(pos) && vi &&
1018 !TTool::getApplication()->getCurrentObject()->isSpline()) {
1019 m_what = GLOBAL_THICKNESS;
1020 m_cursorId = ToolCursor::PumpCursor;
1021 return;
1022 }
1023 }
1024 m_selectedPoint = NONE;
1025 if ((isLevelType() || isSelectedFramesType()) && !isSameStyleType()) {
1026 m_what = Inside;
1027 m_cursorId = ToolCursor::LevelSelectCursor;
1028 }
1029
1030 if (shift) return;
1031 if (!vi && bbox.contains(pos)) {
1032 m_what = Inside;
1033 if (isLevelType() || isSelectedFramesType())
1034 m_cursorId = ToolCursor::LevelSelectCursor;
1035 else
1036 m_cursorId = ToolCursor::MoveCursor;
1037 }
1038 }
1039
1040 //-----------------------------------------------------------------------------
1041
leftButtonDown(const TPointD & pos,const TMouseEvent & e)1042 void SelectionTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
1043 TImageP image = getImage(false);
1044 if (!image) return;
1045 if (m_polyline.size() == 0) {
1046 modifySelectionOnClick(image, pos, e);
1047
1048 if (m_what == ROTATION) m_dragTool = createNewRotationTool(this);
1049 if (!e.isShiftPressed() && m_what == Inside)
1050 m_dragTool = createNewMoveSelectionTool(this);
1051 else if (m_what == MOVE_CENTER)
1052 m_dragTool = new MoveCenterTool(this);
1053 else if (m_what == SCALE)
1054 m_dragTool = createNewScaleTool(this, ScaleType::GLOBAL);
1055 else if (m_what == SCALE_X)
1056 m_dragTool = createNewScaleTool(this, ScaleType::HORIZONTAL);
1057 else if (m_what == SCALE_Y)
1058 m_dragTool = createNewScaleTool(this, ScaleType::VERTICAL);
1059 else if (m_what == DEFORM)
1060 m_dragTool = createNewFreeDeformTool(this);
1061 else if (m_what == GLOBAL_THICKNESS)
1062 m_dragTool = new VectorChangeThicknessTool((VectorSelectionTool *)this);
1063 if (m_dragTool) m_dragTool->leftButtonDown(pos, e);
1064 } else
1065 m_selecting = true;
1066 if (m_selecting) {
1067 if (m_stroke) {
1068 delete m_stroke;
1069 m_stroke = 0;
1070 }
1071 if (m_strokeSelectionType.getValue() == FREEHAND_SELECTION)
1072 startFreehand(pos);
1073 if (m_strokeSelectionType.getValue() == POLYLINE_SELECTION)
1074 addPointPolyline(pos);
1075 else if (m_polyline.size() != 0)
1076 m_polyline.clear();
1077 }
1078 m_firstPos = m_curPos = pos;
1079 m_leftButtonMousePressed = true;
1080 m_shiftPressed = e.isShiftPressed();
1081 }
1082
1083 //-----------------------------------------------------------------------------
1084
mouseMove(const TPointD & pos,const TMouseEvent & e)1085 void SelectionTool::mouseMove(const TPointD &pos, const TMouseEvent &e) {
1086 updateAction(pos, e);
1087
1088 if (m_strokeSelectionType.getValue() == POLYLINE_SELECTION) {
1089 m_mousePosition = pos;
1090 invalidate();
1091 }
1092 }
1093
1094 //-----------------------------------------------------------------------------
1095
keyDown(QKeyEvent * event)1096 bool SelectionTool::keyDown(QKeyEvent *event) {
1097 if (isSelectionEmpty()) return false;
1098
1099 TPointD delta;
1100
1101 switch (event->key()) {
1102 case Qt::Key_Up:
1103 delta.y = 1;
1104 break;
1105 case Qt::Key_Down:
1106 delta.y = -1;
1107 break;
1108 case Qt::Key_Left:
1109 delta.x = -1;
1110 break;
1111 case Qt::Key_Right:
1112 delta.x = 1;
1113 break;
1114 default:
1115 return false;
1116 break;
1117 }
1118
1119 if (event->modifiers() & Qt::ShiftModifier) {
1120 delta.x *= 10.0;
1121 delta.y *= 10.0;
1122 } else if (event->modifiers() & Qt::ControlModifier) {
1123 delta.x *= 0.1;
1124 delta.y *= 0.1;
1125 }
1126
1127 TImageP image = getImage(true);
1128
1129 TToonzImageP ti = (TToonzImageP)image;
1130 TRasterImageP ri = (TRasterImageP)image;
1131 TVectorImageP vi = (TVectorImageP)image;
1132
1133 if (!ti && !vi && !ri) return false;
1134
1135 std::unique_ptr<DragTool> dragTool(createNewMoveSelectionTool(this));
1136 TAffine aff = TTranslation(delta);
1137 dragTool->transform(aff);
1138 double factor = 1.0 / Stage::inch;
1139 m_deformValues.m_moveValue += factor * delta;
1140 dragTool->addTransformUndo();
1141 TTool::getApplication()->getCurrentTool()->notifyToolChanged();
1142
1143 invalidate();
1144 return true;
1145 }
1146
1147 //-----------------------------------------------------------------------------
1148
getCursorId() const1149 int SelectionTool::getCursorId() const {
1150 TImageP image = getImage(false);
1151 TToonzImageP ti = (TToonzImageP)image;
1152 TRasterImageP ri = (TRasterImageP)image;
1153 TVectorImageP vi = (TVectorImageP)image;
1154
1155 if (!ti && !vi && !ri) return ToolCursor::StrokeSelectCursor;
1156
1157 return m_cursorId;
1158 }
1159
1160 //-----------------------------------------------------------------------------
1161
drawPolylineSelection()1162 void SelectionTool::drawPolylineSelection() {
1163 if (m_polyline.empty()) return;
1164 TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg
1165 ? TPixel32::White
1166 : TPixel32::Black;
1167 tglColor(color);
1168 tglDrawCircle(m_polyline[0], 2);
1169 glBegin(GL_LINE_STRIP);
1170 for (UINT i = 0; i < m_polyline.size(); i++) tglVertex(m_polyline[i]);
1171 tglVertex(m_mousePosition);
1172 glEnd();
1173 }
1174
1175 //-----------------------------------------------------------------------------
1176
drawFreehandSelection()1177 void SelectionTool::drawFreehandSelection() {
1178 if (m_track.isEmpty()) return;
1179 TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg
1180 ? TPixel32::White
1181 : TPixel32::Black;
1182 tglColor(color);
1183 m_track.drawAllFragments();
1184 }
1185
1186 //-----------------------------------------------------------------------------
1187
drawRectSelection(const TImage * image)1188 void SelectionTool::drawRectSelection(const TImage *image) {
1189 const TVectorImage *vi = dynamic_cast<const TVectorImage *>(image);
1190 unsigned short stipple = 0x3F33;
1191 FourPoints selectingRect = m_selectingRect;
1192 if (vi && m_curPos.x >= m_firstPos.x) stipple = 0xFF00;
1193 drawFourPoints(selectingRect, TPixel32::Black, stipple, true);
1194 }
1195
1196 //-----------------------------------------------------------------------------
1197
drawCommandHandle(const TImage * image)1198 void SelectionTool::drawCommandHandle(const TImage *image) {
1199 const TVectorImage *vi = dynamic_cast<const TVectorImage *>(image);
1200 TPixel32 frameColor(210, 210, 210);
1201 TPixel32 frameColor2(0, 0, 0);
1202 FourPoints rect = getBBox();
1203
1204 drawFourPoints(rect, frameColor, 0xffff, true);
1205
1206 tglColor(frameColor);
1207
1208 if (m_dragTool) m_dragTool->draw();
1209
1210 if (!isSelectionEditable()) return;
1211
1212 double pixelSize = getPixelSize();
1213 if (!isLevelType() && !isSelectedFramesType()) {
1214 TPointD c = getCenter() + TPointD(-pixelSize, +pixelSize);
1215
1216 tglColor(frameColor);
1217 tglDrawCircle(c, pixelSize * 5);
1218 tglDrawSegment(c - TPointD(pixelSize * 15, 0),
1219 c + TPointD(pixelSize * 15, 0));
1220 tglDrawSegment(c - TPointD(0, pixelSize * 15),
1221 c + TPointD(0, pixelSize * 15));
1222 tglColor(frameColor2);
1223 tglDrawCircle(getCenter(), pixelSize * 5);
1224 tglDrawSegment(getCenter() - TPointD(pixelSize * 15, 0),
1225 getCenter() + TPointD(pixelSize * 15, 0));
1226 tglDrawSegment(getCenter() - TPointD(0, pixelSize * 15),
1227 getCenter() + TPointD(0, pixelSize * 15));
1228 }
1229
1230 TPointD bl(rect.getP00().x - pixelSize, rect.getP00().y + pixelSize);
1231 TPointD tl(rect.getP01().x - pixelSize, rect.getP01().y + pixelSize);
1232 TPointD br(rect.getP10().x - pixelSize, rect.getP10().y + pixelSize);
1233 TPointD tr(rect.getP11().x - pixelSize, rect.getP11().y + pixelSize);
1234
1235 drawSquare(bl, pixelSize * 4, frameColor);
1236 drawSquare(tl, pixelSize * 4, frameColor);
1237 drawSquare(br, pixelSize * 4, frameColor);
1238 drawSquare(tr, pixelSize * 4, frameColor);
1239
1240 drawSquare(rect.getP00(), pixelSize * 4, frameColor2);
1241 drawSquare(rect.getP01(), pixelSize * 4, frameColor2);
1242 drawSquare(rect.getP10(), pixelSize * 4, frameColor2);
1243 drawSquare(rect.getP11(), pixelSize * 4, frameColor2);
1244
1245 if (vi && !m_deformValues.m_isSelectionModified) {
1246 TPointD thickCommandPos =
1247 rect.getP10() - TPointD(14 * pixelSize, 15 * pixelSize);
1248 drawRectWhitArrow(thickCommandPos, pixelSize);
1249 }
1250
1251 drawSquare(0.5 * (br + tr), pixelSize * 4, frameColor);
1252 drawSquare(0.5 * (tl + tr), pixelSize * 4, frameColor);
1253 drawSquare(0.5 * (br + bl), pixelSize * 4, frameColor);
1254 drawSquare(0.5 * (tl + bl), pixelSize * 4, frameColor);
1255
1256 drawSquare(0.5 * (rect.getP10() + rect.getP11()), pixelSize * 4, frameColor2);
1257 drawSquare(0.5 * (rect.getP01() + rect.getP11()), pixelSize * 4, frameColor2);
1258 drawSquare(0.5 * (rect.getP10() + rect.getP00()), pixelSize * 4, frameColor2);
1259 drawSquare(0.5 * (rect.getP01() + rect.getP00()), pixelSize * 4, frameColor2);
1260 }
1261
1262 //-----------------------------------------------------------------------------
1263
onActivate()1264 void SelectionTool::onActivate() {
1265 if (m_firstTime) {
1266 m_strokeSelectionType.setValue(::to_wstring(SelectionType.getValue()));
1267 m_firstTime = false;
1268 }
1269 if (isLevelType() || isSelectedFramesType()) return;
1270
1271 doOnActivate();
1272 }
1273
1274 //-----------------------------------------------------------------------------
1275
onDeactivate()1276 void SelectionTool::onDeactivate() {
1277 if (isLevelType() || isSelectedFramesType()) return;
1278
1279 doOnDeactivate();
1280 }
1281
1282 //-----------------------------------------------------------------------------
1283
onSelectionChanged()1284 void SelectionTool::onSelectionChanged() {
1285 computeBBox();
1286 invalidate();
1287 m_polyline.clear();
1288 }
1289
1290 //-----------------------------------------------------------------------------
1291
onPropertyChanged(std::string propertyName)1292 bool SelectionTool::onPropertyChanged(std::string propertyName) {
1293 if (propertyName == m_strokeSelectionType.getName()) {
1294 SelectionType = ::to_string(m_strokeSelectionType.getValue());
1295 return true;
1296 }
1297 return false;
1298 }
1299
1300 //-----------------------------------------------------------------------------
1301
1302 //! Viene aggiunto \b pos a \b m_track e disegnato il primo pezzetto del lazzo.
1303 //! Viene inizializzato \b m_firstPos
startFreehand(const TPointD & pos)1304 void SelectionTool::startFreehand(const TPointD &pos) {
1305 m_track.clear();
1306 m_firstPos = pos;
1307 double pixelSize = getPixelSize();
1308 m_track.add(TThickPoint(pos, 0), pixelSize * pixelSize);
1309 }
1310
1311 //-----------------------------------------------------------------------------
1312
1313 //! Viene aggiunto \b pos a \b m_track e disegnato un altro pezzetto del lazzo.
freehandDrag(const TPointD & pos)1314 void SelectionTool::freehandDrag(const TPointD &pos) {
1315 double pixelSize = getPixelSize();
1316 m_track.add(TThickPoint(pos, 0), pixelSize * pixelSize);
1317 }
1318
1319 //-----------------------------------------------------------------------------
1320
1321 //! Viene chiuso il lazzo (si aggiunge l'ultimo punto ad m_track) e viene creato
1322 //! lo stroke rappresentante il lazzo.
closeFreehand(const TPointD & pos)1323 void SelectionTool::closeFreehand(const TPointD &pos) {
1324 if (m_track.isEmpty()) return;
1325 double pixelSize = getPixelSize();
1326 m_track.add(TThickPoint(m_firstPos, 0), pixelSize * pixelSize);
1327 m_track.filterPoints();
1328 double error = (30.0 / 11) * pixelSize;
1329 m_stroke = m_track.makeStroke(error);
1330 m_stroke->setStyle(1);
1331 }
1332
1333 //-----------------------------------------------------------------------------
1334
1335 //! Viene aggiunto un punto al vettore m_polyline.
addPointPolyline(const TPointD & pos)1336 void SelectionTool::addPointPolyline(const TPointD &pos) {
1337 m_firstPos = pos;
1338 m_mousePosition = pos;
1339 m_polyline.push_back(pos);
1340 }
1341
1342 //-----------------------------------------------------------------------------
1343
1344 //! Agginge l'ultimo pos a \b m_polyline e chiude la spezzata (aggiunge \b
1345 //! m_polyline.front() alla fine del vettore).
closePolyline(const TPointD & pos)1346 void SelectionTool::closePolyline(const TPointD &pos) {
1347 if (m_polyline.size() <= 1) return;
1348 if (m_polyline.back() != pos) m_polyline.push_back(pos);
1349 if (m_polyline.back() != m_polyline.front())
1350 m_polyline.push_back(m_polyline.front());
1351
1352 std::vector<TThickPoint> strokePoints;
1353 for (UINT i = 0; i < m_polyline.size() - 1; i++) {
1354 strokePoints.push_back(TThickPoint(m_polyline[i], 0));
1355 strokePoints.push_back(
1356 TThickPoint(0.5 * (m_polyline[i] + m_polyline[i + 1]), 0));
1357 }
1358 strokePoints.push_back(TThickPoint(m_polyline.back(), 0));
1359 m_polyline.clear();
1360 m_stroke = new TStroke(strokePoints);
1361 assert(m_stroke->getPoint(0) == m_stroke->getPoint(1));
1362 invalidate();
1363 }
1364
1365 //-----------------------------------------------------------------------------
1366
1367 // returns true if the pressed key is recognized and processed in the tool
1368 // instead of triggering the shortcut command.
isEventAcceptable(QEvent * e)1369 bool SelectionTool::isEventAcceptable(QEvent *e) {
1370 if (!isEnabled()) return false;
1371 if (isSelectionEmpty()) return false;
1372 // arrow keys will be used for moving the selected region
1373 QKeyEvent *keyEvent = static_cast<QKeyEvent *>(e);
1374 int key = keyEvent->key();
1375 return (key == Qt::Key_Up || key == Qt::Key_Down || key == Qt::Key_Left ||
1376 key == Qt::Key_Right);
1377 }
1378