1 #pragma once
2 
3 #ifndef SELECTIONTOOL_INCLUDED
4 #define SELECTIONTOOL_INCLUDED
5 
6 #include "tproperty.h"
7 #include "toonzqt/selection.h"
8 #include "tools/toolutils.h"
9 #include "toonz/strokegenerator.h"
10 
11 // For Qt translation support
12 #include <QCoreApplication>
13 #include <QSet>
14 
15 class SelectionTool;
16 
17 //=============================================================================
18 // Constants / Defines
19 //-----------------------------------------------------------------------------
20 
21 enum SelectionType {
22   RECT_SELECTION_IDX,
23   FREEHAND_SELECTION_IDX,
24   POLYLINE_SELECTION_IDX,
25 };
26 
27 #define RECT_SELECTION L"Rectangular"
28 #define FREEHAND_SELECTION L"Freehand"
29 #define POLYLINE_SELECTION L"Polyline"
30 
31 //=============================================================================
32 // FreeDeformer
33 //-----------------------------------------------------------------------------
34 
35 class FreeDeformer {
36 protected:
37   TPointD m_originalP00;
38   TPointD m_originalP11;
39 
40   std::vector<TPointD> m_newPoints;
41 
42 public:
FreeDeformer()43   FreeDeformer() {}
~FreeDeformer()44   virtual ~FreeDeformer() {}
45 
46   /*! Set \b index point to \b p, with index from 0 to 3. */
47   virtual void setPoint(int index, const TPointD &p) = 0;
48   /*! Helper function. */
49   virtual void setPoints(const TPointD &p0, const TPointD &p1,
50                          const TPointD &p2, const TPointD &p3) = 0;
51   virtual void deformImage() = 0;
52 };
53 
54 //=============================================================================
55 // DragSelectionTool
56 //-----------------------------------------------------------------------------
57 namespace DragSelectionTool {
58 //-----------------------------------------------------------------------------
59 
60 //=============================================================================
61 // FourPoints
62 //-----------------------------------------------------------------------------
63 
64 class FourPoints {
65   TPointD m_p00, m_p01, m_p10, m_p11;
66 
67 public:
FourPoints(TPointD p00,TPointD p01,TPointD p10,TPointD p11)68   FourPoints(TPointD p00, TPointD p01, TPointD p10, TPointD p11)
69       : m_p00(p00), m_p01(p01), m_p10(p10), m_p11(p11) {}
FourPoints()70   FourPoints()
71       : m_p00(TPointD())
72       , m_p01(TPointD())
73       , m_p10(TPointD())
74       , m_p11(TPointD()) {}
75 
setP00(TPointD p)76   void setP00(TPointD p) { m_p00 = p; }
setP01(TPointD p)77   void setP01(TPointD p) { m_p01 = p; }
setP10(TPointD p)78   void setP10(TPointD p) { m_p10 = p; }
setP11(TPointD p)79   void setP11(TPointD p) { m_p11 = p; }
80 
getP00()81   TPointD getP00() const { return m_p00; }
getP01()82   TPointD getP01() const { return m_p01; }
getP10()83   TPointD getP10() const { return m_p10; }
getP11()84   TPointD getP11() const { return m_p11; }
85 
86   /*! Order four point from BottomLeft to TopRight. */
87   FourPoints orderedPoints() const;
getBottomLeft()88   TPointD getBottomLeft() const { return orderedPoints().getP00(); }
getBottomRight()89   TPointD getBottomRight() const { return orderedPoints().getP10(); }
getTopRight()90   TPointD getTopRight() const { return orderedPoints().getP11(); }
getTopLeft()91   TPointD getTopLeft() const { return orderedPoints().getP01(); }
92 
93   /*! Point = index: P00 =  0; P10 = 1; P11 = 2; P01 = 3; P0M = 4; P1M = 5; PM1
94    * = 6; P0M = 7. */
95   TPointD getPoint(int index) const;
96   /*! Point = index: P00 =  0; P10 = 1; P11 = 2; P01 = 3. */
97   void setPoint(int index, const TPointD &p);
98 
99   FourPoints enlarge(double d);
100   bool isEmpty();
101   void empty();
102   bool contains(TPointD p);
103   TRectD getBox() const;
104   FourPoints &operator=(const TRectD &r);
105   bool operator==(const FourPoints &p) const;
106   FourPoints operator*(const TAffine &aff) const;
107 };
108 
109 //=============================================================================
110 void drawFourPoints(const FourPoints &rect, const TPixel32 &color,
111                     unsigned short stipple, bool doContrast);
112 //-----------------------------------------------------------------------------
113 
114 //=============================================================================
115 // DeformValues
116 //-----------------------------------------------------------------------------
117 
118 struct DeformValues {
119   double m_rotationAngle, m_maxSelectionThickness;
120   TPointD m_scaleValue, m_moveValue;
121   bool m_isSelectionModified;
122 
123   DeformValues(double rotationAngle = 0, double maxSelectionThickness = 0,
124                TPointD scaleValue = TPointD(1, 1),
125                TPointD moveValue = TPointD(), bool isSelectionModified = false)
m_rotationAngleDeformValues126       : m_rotationAngle(rotationAngle)
127       , m_maxSelectionThickness(maxSelectionThickness)
128       , m_scaleValue(scaleValue)
129       , m_moveValue(moveValue)
130       , m_isSelectionModified(isSelectionModified) {}
131 
resetDeformValues132   void reset() {
133     m_rotationAngle         = 0;
134     m_maxSelectionThickness = 0;
135     m_scaleValue            = TPointD(1, 1);
136     m_moveValue             = TPointD();
137     m_isSelectionModified   = false;
138   }
139 };
140 
141 //=============================================================================
142 // DragTool
143 //-----------------------------------------------------------------------------
144 
145 class DragTool {
146 protected:
147   SelectionTool *m_tool;
148 
149 public:
DragTool(SelectionTool * tool)150   DragTool(SelectionTool *tool) : m_tool(tool) {}
~DragTool()151   virtual ~DragTool() {}
152 
getTool()153   SelectionTool *getTool() const { return m_tool; }
154 
transform(TAffine aff,double angle)155   virtual void transform(TAffine aff, double angle){}
transform(TAffine aff)156   virtual void transform(TAffine aff){}
transform(int index,TPointD newPos)157   virtual TPointD transform(int index, TPointD newPos) { return TPointD(); }
addTransformUndo()158   virtual void addTransformUndo(){}
159 
160   virtual void leftButtonDown(const TPointD &pos, const TMouseEvent &) = 0;
161   virtual void leftButtonDrag(const TPointD &pos, const TMouseEvent &) = 0;
162   virtual void leftButtonUp(const TPointD &pos, const TMouseEvent &)   = 0;
163   virtual void draw() = 0;
164 };
165 
166 //=============================================================================
167 // DeformTool
168 //-----------------------------------------------------------------------------
169 
170 class DeformTool : public DragTool {
171 protected:
172   TPointD m_curPos;
173   bool m_isDragging;
174   TPointD m_startScaleValue;
175   TPointD m_startPos;
176 
177 public:
178   DeformTool(SelectionTool *tool);
179 
180   virtual void applyTransform(FourPoints bbox) = 0;
applyTransform(TAffine aff)181   virtual void applyTransform(TAffine aff){};
182 
183   void addTransformUndo() override = 0;
184 
185   int getSymmetricPointIndex(int index) const;
186   /*! Return before point \b index between possible point index
187    * {0,4,1,5,2,6,3,7}, include middle point. */
188   int getBeforePointIndex(int index) const;
189   /*! Return next point \b index between possible point index {0,4,1,5,2,6,3,7},
190    * include middle point. */
191   int getNextPointIndex(int index) const;
192   /*! Return before vertex \b index between possible point vertex index
193    * {0,1,2,3}*/
194   int getBeforeVertexIndex(int index) const;
195   /*! Return next vertex \b index between possible point vertex index
196    * {0,1,2,3}*/
197   int getNextVertexIndex(int index) const;
198 
getStartPos()199   TPointD getStartPos() const { return m_startPos; }
setStartPos(const TPointD & pos)200   void setStartPos(const TPointD &pos) { m_startPos = pos; }
getCurPos()201   TPointD getCurPos() const { return m_curPos; }
setCurPos(const TPointD & pos)202   void setCurPos(const TPointD &pos) { m_curPos = pos; }
isDragging()203   bool isDragging() const { return m_isDragging; }
getStartScaleValue()204   TPointD getStartScaleValue() const { return m_startScaleValue; }
205 
206   void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override;
207   void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override = 0;
208   void leftButtonUp(const TPointD &pos, const TMouseEvent &e) override;
209   void draw() override = 0;
210 };
211 
212 //=============================================================================
213 // Rotation
214 //-----------------------------------------------------------------------------
215 
216 class Rotation {
217   double m_curAng, m_dstAng;
218   DeformTool *m_deformTool;
219 
220 public:
221   Rotation(DeformTool *deformTool);
222   TPointD getStartCenter() const;
223   void leftButtonDrag(const TPointD &pos, const TMouseEvent &e);
224   void draw();
225 };
226 
227 //=============================================================================
228 // FreeDeform
229 //-----------------------------------------------------------------------------
230 
231 class FreeDeform {
232   DeformTool *m_deformTool;
233 
234 public:
235   FreeDeform(DeformTool *deformTool);
236   void leftButtonDrag(const TPointD &pos, const TMouseEvent &e);
237 };
238 
239 //=============================================================================
240 // MoveSelection
241 //-----------------------------------------------------------------------------
242 
243 class MoveSelection {
244   DeformTool *m_deformTool;
245   TPointD m_lastDelta, m_firstPos;
246 
247 public:
248   MoveSelection(DeformTool *deformTool);
249   void leftButtonDown(const TPointD &pos, const TMouseEvent &e);
250   void leftButtonDrag(const TPointD &pos, const TMouseEvent &e);
251 };
252 
253 //=============================================================================
254 // Scale
255 //-----------------------------------------------------------------------------
256 
257 enum class ScaleType {
258   GLOBAL = 0,
259   HORIZONTAL,
260   VERTICAL
261 };
262 
263 class Scale {
264   TPointD m_startCenter;
265   bool m_isShiftPressed;
266   bool m_isAltPressed;
267   bool m_scaleInCenter;
268   std::vector<FourPoints> m_startBboxs;
269 
270   DeformTool *m_deformTool;
271 
272 public:
273 
274   ScaleType m_type;
275   Scale(DeformTool *deformTool, ScaleType type);
276 
277   /*! Return intersection between straight line in \b point0, \b point1 and
278 straight line for
279 \b p parallel to straight line in \b point2, \b point3. */
280   TPointD getIntersectionPoint(const TPointD &point0, const TPointD &point1,
281                                const TPointD &point2, const TPointD &point3,
282                                const TPointD &p) const;
283   /*! Scale \b index point of \b bbox in \b pos and return scaled bbox. */
284   FourPoints bboxScale(int index, const FourPoints &oldBbox,
285                        const TPointD &pos);
286   /*! Compute new scale value take care of new position of \b movedIndex point
287    * in \b bbox. */
288   TPointD computeScaleValue(int movedIndex, const FourPoints newBbox);
289   /*! Return \b index point scaled in \b center of \b scaleValue. */
290   TPointD getScaledPoint(int index, const FourPoints &oldBbox,
291                          const TPointD scaleValue, const TPointD center);
292   /*! Compute new center after scale of \b bbox \b index point. */
293   TPointD getNewCenter(int index, const FourPoints bbox,
294                        const TPointD scaleValue);
295   /*! Scale \b bbox \b index point in pos and if \b m_scaleInCenter is true
296 scale in \b center \b bbox symmetric point;
297 compute scaleValue. */
298   FourPoints bboxScaleInCenter(int index, const FourPoints &oldBbox,
299                                const TPointD newPos, TPointD &scaleValue,
300                                const TPointD center, bool recomputeScaleValue);
301 
302   void leftButtonDown(const TPointD &pos, const TMouseEvent &e);
303   void leftButtonDrag(const TPointD &pos, const TMouseEvent &e);
304 
getStartBboxs()305   std::vector<FourPoints> getStartBboxs() const { return m_startBboxs; }
getStartCenter()306   TPointD getStartCenter() const { return m_startCenter; }
scaleInCenter()307   bool scaleInCenter() const { return m_scaleInCenter; }
308 };
309 };
310 
311 //=============================================================================
312 // Utility
313 //-----------------------------------------------------------------------------
314 
315 DragSelectionTool::DragTool *createNewMoveSelectionTool(SelectionTool *st);
316 DragSelectionTool::DragTool *createNewRotationTool(SelectionTool *st);
317 DragSelectionTool::DragTool *createNewFreeDeformTool(SelectionTool *st);
318 DragSelectionTool::DragTool *createNewScaleTool(SelectionTool *st, DragSelectionTool::ScaleType type);
319 
320 //=============================================================================
321 // SelectionTool
322 //-----------------------------------------------------------------------------
323 
324 class SelectionTool : public TTool, public TSelection::View {
325   Q_DECLARE_TR_FUNCTIONS(SelectionTool)
326 
327 protected:
328   bool m_firstTime;
329   DragSelectionTool::DragTool *m_dragTool;
330 
331   StrokeGenerator m_track;
332   std::vector<TPointD> m_polyline;
333   TPointD m_mousePosition;
334   TStroke *m_stroke;
335 
336   // To modify selection
337   TPointD m_curPos;
338   TPointD m_firstPos;
339 
340   bool m_selecting;
341   bool m_justSelected;
342   bool m_shiftPressed;
343 
344   enum {
345     Outside,
346     Inside,
347     DEFORM,
348     ROTATION,
349     MOVE_CENTER,
350     SCALE,
351     SCALE_X,
352     SCALE_Y,
353     GLOBAL_THICKNESS,
354     ADD_SELECTION
355   } m_what;  // RV
356 
357   enum {
358     P00 = 0,
359     P10 = 1,
360     P11 = 2,
361     P01 = 3,
362     PM0 = 4,
363     P1M = 5,
364     PM1 = 6,
365     P0M = 7,
366     NONE
367   } m_selectedPoint;  // RV
368 
369   int m_cursorId;
370 
371   bool m_leftButtonMousePressed;
372 
373   DragSelectionTool::FourPoints m_selectingRect;
374 
375   std::vector<DragSelectionTool::FourPoints> m_bboxs;
376   std::vector<TPointD> m_centers;
377   std::vector<FreeDeformer *> m_freeDeformers;
378 
379   TEnumProperty m_strokeSelectionType;
380   TPropertyGroup m_prop;
381 
382   virtual void updateAction(TPointD pos, const TMouseEvent &e);
383 
384   virtual void modifySelectionOnClick(TImageP image, const TPointD &pos,
385                                       const TMouseEvent &e) = 0;
386 
387   virtual void doOnActivate()   = 0;
388   virtual void doOnDeactivate() = 0;
389 
390   // Metodi per disegnare la linea della selezione Freehand
391   void startFreehand(const TPointD &pos);
392   void freehandDrag(const TPointD &pos);
393   void closeFreehand(const TPointD &pos);
394 
395   // Metodi per disegnare la linea della selezione Polyline
396   void addPointPolyline(const TPointD &pos);
397   void closePolyline(const TPointD &pos);
398 
399   void updateTranslation() override;
400 
401   void drawPolylineSelection();
402   void drawRectSelection(const TImage *image);
403   void drawFreehandSelection();
404   void drawCommandHandle(const TImage *image);
405 
406 public:
407   DragSelectionTool::DeformValues m_deformValues;
408 
409   SelectionTool(int targetType);
410   ~SelectionTool() override;
411 
getToolType()412   ToolType getToolType() const override { return TTool::LevelWriteTool; }
413 
414   TPointD getCenter(int index = 0) const;
415   void setCenter(const TPointD &center, int index = 0);
416 
417   int getBBoxsCount() const;
418   DragSelectionTool::FourPoints getBBox(int index = 0) const;
419   virtual void setBBox(const DragSelectionTool::FourPoints &points,
420                        int index = 0);
421 
422   FreeDeformer *getFreeDeformer(int index = 0) const;
423   virtual void setNewFreeDeformer()       = 0;
424   void clearDeformers();
425 
getSelectedPoint()426   int getSelectedPoint() const { return m_selectedPoint; }
427 
isConstantThickness()428   virtual bool isConstantThickness() const { return true; }
isLevelType()429   virtual bool isLevelType() const { return false; }
isSelectedFramesType()430   virtual bool isSelectedFramesType() const { return false; }
isSameStyleType()431   virtual bool isSameStyleType() const { return false; }
isModifiableSelectionType()432   virtual bool isModifiableSelectionType() const {
433     return !(isLevelType() || isSelectedFramesType());
434   }
isFloating()435   virtual bool isFloating() const { return false; }
436 
getSelectedStyles()437   virtual QSet<int> getSelectedStyles() const { return QSet<int>(); }
438 
439   void leftButtonDown(const TPointD &pos, const TMouseEvent &) override;
440   void leftButtonDrag(const TPointD &pos, const TMouseEvent &) override = 0;
441   void leftButtonUp(const TPointD &pos, const TMouseEvent &) override   = 0;
442   void mouseMove(const TPointD &pos, const TMouseEvent &e) override;
443   void leftButtonDoubleClick(const TPointD &,
444                              const TMouseEvent &e) override = 0;
445   bool keyDown(QKeyEvent *) override;
446 
447   int getCursorId() const override;
448 
449   void draw() override = 0;
450 
451   TSelection *getSelection() override = 0;
452   virtual bool isSelectionEmpty()     = 0;
453 
454   virtual void computeBBox() = 0;
455 
456   void onActivate() override;
457   void onDeactivate() override;
458   void onImageChanged() override = 0;
459   void onSelectionChanged() override;
460 
getProperties(int targetType)461   TPropertyGroup *getProperties(int targetType) override { return &m_prop; }
462 
463   bool onPropertyChanged(std::string propertyName) override;
464 
465   // returns true if the pressed key is recognized and processed.
466   bool isEventAcceptable(QEvent *e) override;
467 
isSelectionEditable()468   virtual bool isSelectionEditable() { return true; }
469 };
470 
471 #endif  // SELECTIONTOOL_INCLUDED
472