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 ¢er, 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