Pencil2D Animation
Download Community News Docs Contribute

core_lib/src/tool/erasertool.cpp Source File

  • Main Page
  • Related Pages
  • Classes
  • Files
  •  
  • File List
Loading...
Searching...
No Matches
  • core_lib
  • src
  • tool
erasertool.cpp
1/*
2
3Pencil2D - Traditional Animation Software
4Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
5Copyright (C) 2012-2020 Matthew Chiawen Chang
6
7This program is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public License
9as published by the Free Software Foundation; version 2 of the License.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16*/
17#include "erasertool.h"
18
19#include <QSettings>
20#include <QPixmap>
21#include <QPainter>
22
23#include "editor.h"
24#include "blitrect.h"
25#include "scribblearea.h"
26#include "strokemanager.h"
27#include "layermanager.h"
28#include "viewmanager.h"
29#include "layervector.h"
30#include "vectorimage.h"
31#include "pointerevent.h"
32
33
34EraserTool::EraserTool(QObject* parent) : StrokeTool(parent)
35{
36}
37
38ToolType EraserTool::type()
39{
40 return ERASER;
41}
42
43void EraserTool::loadSettings()
44{
45 mPropertyEnabled[WIDTH] = true;
46 mPropertyEnabled[USEFEATHER] = true;
47 mPropertyEnabled[FEATHER] = true;
48 mPropertyEnabled[USEFEATHER] = true;
49 mPropertyEnabled[PRESSURE] = true;
50 mPropertyEnabled[STABILIZATION] = true;
51 mPropertyEnabled[ANTI_ALIASING] = true;
52
53 QSettings settings(PENCIL2D, PENCIL2D);
54
55 properties.width = settings.value("eraserWidth", 24.0).toDouble();
56 properties.feather = settings.value("eraserFeather", 48.0).toDouble();
57 properties.useFeather = settings.value("eraserUseFeather", true).toBool();
58 properties.pressure = settings.value("eraserPressure", true).toBool();
59 properties.invisibility = DISABLED;
60 properties.preserveAlpha = OFF;
61 properties.stabilizerLevel = settings.value("stabilizerLevel", StabilizationLevel::NONE).toInt();
62 properties.useAA = settings.value("eraserAA", 1).toInt();
63
64 if (properties.useFeather) { properties.useAA = -1; }
65
66 mQuickSizingProperties.insert(Qt::ShiftModifier, WIDTH);
67 mQuickSizingProperties.insert(Qt::ControlModifier, FEATHER);
68}
69
70void EraserTool::resetToDefault()
71{
72 setWidth(24.0);
73 setFeather(48.0);
74 setUseFeather(true);
75 setPressure(true);
76 setAA(true);
77 setStabilizerLevel(StabilizationLevel::NONE);
78}
79
80void EraserTool::setWidth(const qreal width)
81{
82 // Set current property
83 properties.width = width;
84
85 // Update settings
86 QSettings settings(PENCIL2D, PENCIL2D);
87 settings.setValue("eraserWidth", width);
88 settings.sync();
89}
90
91void EraserTool::setUseFeather(const bool usingFeather)
92{
93 // Set current property
94 properties.useFeather = usingFeather;
95
96 // Update settings
97 QSettings settings(PENCIL2D, PENCIL2D);
98 settings.setValue("eraserUseFeather", usingFeather);
99 settings.sync();
100}
101
102void EraserTool::setFeather(const qreal feather)
103{
104 // Set current property
105 properties.feather = feather;
106
107 // Update settings
108 QSettings settings(PENCIL2D, PENCIL2D);
109 settings.setValue("eraserFeather", feather);
110 settings.sync();
111}
112
113void EraserTool::setPressure(const bool pressure)
114{
115 // Set current property
116 properties.pressure = pressure;
117
118 // Update settings
119 QSettings settings(PENCIL2D, PENCIL2D);
120 settings.setValue("eraserPressure", pressure);
121 settings.sync();
122}
123
124void EraserTool::setAA(const int AA)
125{
126 // Set current property
127 properties.useAA = AA;
128
129 // Update settings
130 QSettings settings(PENCIL2D, PENCIL2D);
131 settings.setValue("eraserAA", AA);
132 settings.sync();
133}
134
135void EraserTool::setStabilizerLevel(const int level)
136{
137 properties.stabilizerLevel = level;
138
139 QSettings settings(PENCIL2D, PENCIL2D);
140 settings.setValue("stabilizerLevel", level);
141 settings.sync();
142}
143
144
145QCursor EraserTool::cursor()
146{
147 return QCursor(QPixmap(":icons/cross.png"), 10, 10);
148}
149
150void EraserTool::pointerPressEvent(PointerEvent *event)
151{
152 startStroke(event->inputType());
153 mLastBrushPoint = getCurrentPoint();
154 mMouseDownPoint = getCurrentPoint();
155}
156
157void EraserTool::pointerMoveEvent(PointerEvent* event)
158{
159 if (event->buttons() & Qt::LeftButton && event->inputType() == mCurrentInputType)
160 {
161 mCurrentPressure = strokeManager()->getPressure();
162 updateStrokes();
163 if (properties.stabilizerLevel != strokeManager()->getStabilizerLevel())
164 strokeManager()->setStabilizerLevel(properties.stabilizerLevel);
165 }
166}
167
168void EraserTool::pointerReleaseEvent(PointerEvent *event)
169{
170 if (event->inputType() != mCurrentInputType) return;
171
172 mEditor->backup(typeName());
173
174 qreal distance = QLineF(getCurrentPoint(), mMouseDownPoint).length();
175 if (distance < 1)
176 {
177 paintAt(mMouseDownPoint);
178 }
179 else
180 {
181 drawStroke();
182 }
183 removeVectorPaint();
184 endStroke();
185}
186
187// draw a single paint dab at the given location
188void EraserTool::paintAt(QPointF point)
189{
190 Layer* layer = mEditor->layers()->currentLayer();
191 if (layer->type() == Layer::BITMAP)
192 {
193 qreal pressure = (properties.pressure) ? mCurrentPressure : 1.0;
194 qreal opacity = (properties.pressure) ? (mCurrentPressure * 0.5) : 1.0;
195 qreal brushWidth = properties.width * pressure;
196 mCurrentWidth = brushWidth;
197
198 mScribbleArea->drawBrush(point,
199 brushWidth,
200 properties.feather,
201 QColor(255, 255, 255, 255),
202 opacity,
203 properties.useFeather,
204 properties.useAA == ON);
205 }
206}
207
208void EraserTool::drawStroke()
209{
210 StrokeTool::drawStroke();
211 QList<QPointF> p = strokeManager()->interpolateStroke();
212
213 Layer* layer = mEditor->layers()->currentLayer();
214
215 if (layer->type() == Layer::BITMAP)
216 {
217 qreal pressure = (properties.pressure) ? mCurrentPressure : 1.0;
218 qreal opacity = (properties.pressure) ? (mCurrentPressure * 0.5) : 1.0;
219 qreal brushWidth = properties.width * pressure;
220 mCurrentWidth = brushWidth;
221
222 qreal brushStep = (0.5 * brushWidth);
223 brushStep = qMax(1.0, brushStep);
224
225 BlitRect rect;
226
227 QPointF a = mLastBrushPoint;
228 QPointF b = getCurrentPoint();
229
230 qreal distance = 4 * QLineF(b, a).length();
231 int steps = qRound(distance / brushStep);
232
233 for (int i = 0; i < steps; i++)
234 {
235 QPointF point = mLastBrushPoint + (i + 1) * brushStep * (getCurrentPoint() - mLastBrushPoint) / distance;
236
237 mScribbleArea->drawBrush(point,
238 brushWidth,
239 properties.feather,
240 Qt::white,
241 opacity,
242 properties.useFeather,
243 properties.useAA == ON);
244 if (i == (steps - 1))
245 {
246 mLastBrushPoint = getCurrentPoint();
247 }
248 }
249 }
250 else if (layer->type() == Layer::VECTOR)
251 {
252 mCurrentWidth = properties.width;
253 if (properties.pressure)
254 {
255 mCurrentWidth = (mCurrentWidth + (strokeManager()->getPressure() * mCurrentWidth)) * 0.5;
256 }
257 qreal brushWidth = mCurrentWidth;
258
259 QPen pen(Qt::white, brushWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
260
261 if (p.size() == 4)
262 {
263 QPainterPath path(p[0]);
264 path.cubicTo(p[1],
265 p[2],
266 p[3]);
267 mScribbleArea->drawPath(path, pen, Qt::NoBrush, QPainter::CompositionMode_Source);
268 }
269 }
270}
271
272void EraserTool::removeVectorPaint()
273{
274 Layer* layer = mEditor->layers()->currentLayer();
275 if (layer->type() == Layer::BITMAP)
276 {
277 mScribbleArea->paintBitmapBuffer();
278 mScribbleArea->clearBitmapBuffer();
279 }
280 else if (layer->type() == Layer::VECTOR)
281 {
282 mScribbleArea->clearBitmapBuffer();
283 VectorImage* vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
284 if (vectorImage == nullptr) { return; } // Can happen if the first frame is deleted while drawing
285 // Clear the area containing the last point
286 //vectorImage->removeArea(lastPoint);
287 // Clear the temporary pixel path
288 vectorImage->deleteSelectedPoints();
289
290 mEditor->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
291 }
292}
293
294void EraserTool::updateStrokes()
295{
296 Layer* layer = mEditor->layers()->currentLayer();
297 if (layer->type() == Layer::BITMAP || layer->type() == Layer::VECTOR)
298 {
299 drawStroke();
300 }
301
302 if (layer->type() == Layer::VECTOR)
303 {
304 qreal radius = properties.width / 2;
305
306 VectorImage* currKey = static_cast<VectorImage*>(layer->getLastKeyFrameAtPosition(mEditor->currentFrame()));
307 QList<VertexRef> nearbyVertices = currKey->getVerticesCloseTo(getCurrentPoint(), radius);
308 for (auto nearbyVertice : nearbyVertices)
309 {
310 currKey->setSelected(nearbyVertice, true);
311 }
312 }
313}
BlitRect
Definition: blitrect.h:25
Layer
Definition: layer.h:38
LayerVector
Definition: layervector.h:26
PointerEvent
Definition: pointerevent.h:8
StrokeTool
Definition: stroketool.h:29
VectorImage
Definition: vectorimage.h:32
VectorImage::setSelected
void setSelected(int curveNumber, bool YesOrNo)
VectorImage::setSelected.
Definition: vectorimage.cpp:617
VectorImage::deleteSelectedPoints
void deleteSelectedPoints()
VectorImage::deleteSelectedPoints.
Definition: vectorimage.cpp:1031
VectorImage::getVerticesCloseTo
QList< VertexRef > getVerticesCloseTo(QPointF thisPoint, qreal maxDistance)
VectorImage::getVerticesCloseTo.
Definition: vectorimage.cpp:1465
QColor
QCursor
QHash::insert
QHash::iterator insert(const Key &key, const T &value)
QLineF
QLineF::length
qreal length() const const
QList
QList::size
int size() const const
QObject
QObject::event
virtual bool event(QEvent *e)
QPainter::CompositionMode_Source
CompositionMode_Source
QPainterPath
QPen
QPixmap
QPointF
QSettings
Qt::NoBrush
NoBrush
Qt::white
white
Qt::ShiftModifier
ShiftModifier
Qt::LeftButton
LeftButton
Qt::RoundCap
RoundCap
Qt::RoundJoin
RoundJoin
Qt::SolidLine
SolidLine
Generated on Mon Jun 5 2023 19:54:05 for Pencil2D by doxygen 1.9.6 based on revision afd72d68a001f57b4de14011d6ef944ba0717158