All Classes Namespaces Functions Variables Enumerations Properties Pages
selecttool.cpp
1 /*
2 
3 Pencil2D - Traditional Animation Software
4 Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
5 Copyright (C) 2012-2020 Matthew Chiawen Chang
6 
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; version 2 of the License.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 */
17 #include "selecttool.h"
18 #include "pointerevent.h"
19 #include "vectorimage.h"
20 #include "editor.h"
21 #include "strokemanager.h"
22 #include "layervector.h"
23 #include "scribblearea.h"
24 #include "layermanager.h"
25 #include "toolmanager.h"
26 #include "selectionmanager.h"
27 
28 SelectTool::SelectTool(QObject* parent) : BaseTool(parent)
29 {
30 }
31 
32 void SelectTool::loadSettings()
33 {
34  properties.width = -1;
35  properties.feather = -1;
36  properties.stabilizerLevel = -1;
37  properties.useAA = -1;
38 }
39 
40 QCursor SelectTool::cursor()
41 {
42  MoveMode mode = mEditor->select()->getMoveModeForSelectionAnchor(getCurrentPoint());
43  return this->selectMoveCursor(mode, type());
44 }
45 
46 void SelectTool::beginSelection()
47 {
48  // Store original click position for help with selection rectangle.
49  mAnchorOriginPoint = getLastPoint();
50 
51  auto selectMan = mEditor->select();
52  selectMan->calculateSelectionTransformation();
53 
54  // paint and apply the transformation
55  mScribbleArea->paintTransformedSelection();
56  mScribbleArea->applyTransformedSelection();
57  mMoveMode = selectMan->validateMoveMode(getLastPoint());
58 
59  if (selectMan->somethingSelected() && mMoveMode != MoveMode::NONE) // there is something selected
60  {
61  if (mCurrentLayer->type() == Layer::VECTOR)
62  {
63  VectorImage* vectorImage = static_cast<LayerVector*>(mCurrentLayer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
64  if (vectorImage != nullptr) {
65  vectorImage->deselectAll();
66  }
67  }
68 
69  mAnchorOriginPoint = selectMan->whichAnchorPoint(getLastPoint());
70  }
71  else
72  {
73  selectMan->setSelection(QRectF(getCurrentPoint().x(), getCurrentPoint().y(), 1, 1), mEditor->layers()->currentLayer()->type() == Layer::BITMAP);
74  }
75  mScribbleArea->update();
76 }
77 
78 void SelectTool::pointerPressEvent(PointerEvent* event)
79 {
80  mCurrentLayer = mEditor->layers()->currentLayer();
81  if (mCurrentLayer == nullptr) return;
82  if (!mCurrentLayer->isPaintable()) { return; }
83  if (event->button() != Qt::LeftButton) { return; }
84  auto selectMan = mEditor->select();
85 
86  mMoveMode = selectMan->validateMoveMode(getCurrentPoint());
87 
88  selectMan->updatePolygons();
89 
90  beginSelection();
91 }
92 
93 void SelectTool::pointerMoveEvent(PointerEvent*)
94 {
95  mCurrentLayer = mEditor->layers()->currentLayer();
96  if (mCurrentLayer == nullptr) { return; }
97  if (!mCurrentLayer->isPaintable()) { return; }
98  auto selectMan = mEditor->select();
99 
100  if (!selectMan->somethingSelected()) { return; }
101 
102  selectMan->updatePolygons();
103 
104  mScribbleArea->updateToolCursor();
105 
106  if (mScribbleArea->isPointerInUse())
107  {
108  controlOffsetOrigin(getCurrentPoint(), mAnchorOriginPoint);
109 
110  if (mCurrentLayer->type() == Layer::VECTOR)
111  {
112  VectorImage* vectorImage = static_cast<LayerVector*>(mCurrentLayer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
113  if (vectorImage != nullptr) {
114  vectorImage->select(selectMan->myTempTransformedSelectionRect());
115  }
116  }
117  }
118 
119  mScribbleArea->updateCurrentFrame();
120 }
121 
122 void SelectTool::pointerReleaseEvent(PointerEvent* event)
123 {
124  mCurrentLayer = mEditor->layers()->currentLayer();
125  if (mCurrentLayer == nullptr) return;
126  if (event->button() != Qt::LeftButton) return;
127  auto selectMan = mEditor->select();
128 
129  // if there's a small very small distance between current and last point
130  // discard the selection...
131  // TODO: improve by adding a timer to check if the user is deliberately selecting
132  if (QLineF(mAnchorOriginPoint, getCurrentPoint()).length() < 5.0)
133  {
134  mEditor->deselectAll();
135  }
136  if (maybeDeselect())
137  {
138  mEditor->deselectAll();
139  }
140  else
141  {
142  keepSelection();
143  }
144 
145  selectMan->updatePolygons();
146 
147  mScribbleArea->updateToolCursor();
148  mScribbleArea->updateCurrentFrame();
149 // mScribbleArea->setAllDirty();
150 }
151 
152 bool SelectTool::maybeDeselect()
153 {
154  return (!isSelectionPointValid() && mEditor->select()->validateMoveMode(getLastPoint()) == MoveMode::NONE);
155 }
156 
162 {
163  auto selectMan = mEditor->select();
164  if (mCurrentLayer->type() == Layer::BITMAP) {
165  if (!selectMan->myTempTransformedSelectionRect().isValid())
166  {
167  selectMan->setSelection(selectMan->myTempTransformedSelectionRect().normalized(), true);
168  }
169  else
170  {
171  selectMan->setSelection(selectMan->myTempTransformedSelectionRect(), true);
172  }
173  }
174  else if (mCurrentLayer->type() == Layer::VECTOR)
175  {
176  VectorImage* vectorImage = static_cast<LayerVector*>(mCurrentLayer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
177  if (vectorImage == nullptr) { return; }
178  selectMan->setSelection(vectorImage->getSelectionRect(), false);
179  }
180 }
181 
182 void SelectTool::controlOffsetOrigin(QPointF currentPoint, QPointF anchorPoint)
183 {
184  QPointF offset = offsetFromPressPos();
185 
186  if (mMoveMode != MoveMode::NONE)
187  {
188  if (editor()->layers()->currentLayer()->type() == Layer::BITMAP) {
189  offset = QPointF(offset).toPoint();
190  }
191 
192  auto selectMan = mEditor->select();
193 
194  selectMan->adjustSelection(getCurrentPoint(), offset.x(), offset.y(), selectMan->myRotation(), 0);
195  }
196  else
197  {
198  // when the selection is none, manage the selection Origin
199  manageSelectionOrigin(currentPoint, anchorPoint);
200  }
201 }
202 
207 void SelectTool::manageSelectionOrigin(QPointF currentPoint, QPointF originPoint)
208 {
209  qreal mouseX = currentPoint.x();
210  qreal mouseY = currentPoint.y();
211 
212  QRectF selectRect;
213 
214  if (mouseX <= originPoint.x())
215  {
216  selectRect.setLeft(mouseX);
217  selectRect.setRight(originPoint.x());
218  }
219  else
220  {
221  selectRect.setLeft(originPoint.x());
222  selectRect.setRight(mouseX);
223  }
224 
225  if (mouseY <= originPoint.y())
226  {
227  selectRect.setTop(mouseY);
228  selectRect.setBottom(originPoint.y());
229  }
230  else
231  {
232  selectRect.setTop(originPoint.y());
233  selectRect.setBottom(mouseY);
234  }
235 
236  mEditor->select()->setTempTransformedSelectionRect(selectRect);
237 }
238 
239 bool SelectTool::keyPressEvent(QKeyEvent* event)
240 {
241  switch (event->key())
242  {
243  case Qt::Key_Alt:
244  mScribbleArea->setTemporaryTool(MOVE);
245  break;
246  default:
247  break;
248  }
249 
250  // Follow the generic behaviour anyway
251  return false;
252 }
253 
254 QPointF SelectTool::offsetFromPressPos()
255 {
256  return getCurrentPoint() - getCurrentPressPoint();
257 }
void setRight(qreal x)
LeftButton
void deselectAll()
VectorImage::deselectAll.
void update()
void setLeft(qreal x)
void manageSelectionOrigin(QPointF currentPoint, QPointF originPoint)
SelectTool::manageSelectionOrigin switches anchor point when crossing threshold.
Definition: selecttool.cpp:207
qreal x() const const
qreal y() const const
int key() const const
QPoint toPoint() const const
void setBottom(qreal y)
void setTop(qreal y)
void keepSelection()
SelectTool::keepSelection Keep selection rect and normalize if invalid.
Definition: selecttool.cpp:161
Qt::MouseButton button() const
Returns Qt::MouseButton()