18 #include "scribblearea.h"
21 #include <QMessageBox>
22 #include <QPixmapCache>
24 #include "pointerevent.h"
25 #include "beziercurve.h"
28 #include "layerbitmap.h"
29 #include "layervector.h"
30 #include "layercamera.h"
31 #include "bitmapimage.h"
32 #include "vectorimage.h"
34 #include "colormanager.h"
35 #include "toolmanager.h"
36 #include "strokemanager.h"
37 #include "layermanager.h"
38 #include "playbackmanager.h"
39 #include "viewmanager.h"
40 #include "selectionmanager.h"
53 ScribbleArea::~ScribbleArea()
58 bool ScribbleArea::init()
60 mPrefs = mEditor->preference();
61 mDoubleClickTimer =
new QTimer(
this);
63 connect(mPrefs, &PreferenceManager::optionChanged,
this, &ScribbleArea::settingUpdated);
66 connect(mEditor->select(), &SelectionManager::selectionChanged,
this, &ScribbleArea::updateCurrentFrame);
67 connect(mEditor->select(), &SelectionManager::needPaintAndApply,
this, &ScribbleArea::applySelectionChanges);
68 connect(mEditor->select(), &SelectionManager::needDeleteSelection,
this, &ScribbleArea::deleteSelection);
72 const int curveSmoothingLevel = mPrefs->getInt(SETTING::CURVE_SMOOTHING);
73 mCurveSmoothingLevel = curveSmoothingLevel / 20.0;
75 mQuickSizing = mPrefs->isOn(SETTING::QUICK_SIZING);
76 mMakeInvisible =
false;
78 mIsSimplified = mPrefs->isOn(SETTING::OUTLINES);
79 mMultiLayerOnionSkin = mPrefs->isOn(SETTING::MULTILAYER_ONION);
81 mLayerVisibility =
static_cast<LayerVisibility
>(mPrefs->getInt(SETTING::LAYER_VISIBILITY));
89 #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
96 mPixmapCacheKeys.
clear();
101 void ScribbleArea::settingUpdated(SETTING setting)
105 case SETTING::CURVE_SMOOTHING:
106 setCurveSmoothing(mPrefs->getInt(SETTING::CURVE_SMOOTHING));
108 case SETTING::TOOL_CURSOR:
111 case SETTING::ONION_PREV_FRAMES_NUM:
112 case SETTING::ONION_NEXT_FRAMES_NUM:
113 case SETTING::ONION_MIN_OPACITY:
114 case SETTING::ONION_MAX_OPACITY:
115 case SETTING::ANTIALIAS:
117 case SETTING::GRID_SIZE_W:
118 case SETTING::GRID_SIZE_H:
119 case SETTING::OVERLAY_CENTER:
120 case SETTING::OVERLAY_THIRDS:
121 case SETTING::OVERLAY_GOLDEN:
122 case SETTING::OVERLAY_SAFE:
123 case SETTING::ACTION_SAFE_ON:
124 case SETTING::ACTION_SAFE:
125 case SETTING::TITLE_SAFE_ON:
126 case SETTING::TITLE_SAFE:
127 case SETTING::OVERLAY_SAFE_HELPER_TEXT_ON:
128 case SETTING::PREV_ONION:
129 case SETTING::NEXT_ONION:
130 case SETTING::ONION_BLUE:
131 case SETTING::ONION_RED:
132 case SETTING::INVISIBLE_LINES:
133 case SETTING::OUTLINES:
134 case SETTING::ONION_TYPE:
137 case SETTING::QUICK_SIZING:
138 mQuickSizing = mPrefs->isOn(SETTING::QUICK_SIZING);
140 case SETTING::MULTILAYER_ONION:
141 mMultiLayerOnionSkin = mPrefs->isOn(SETTING::MULTILAYER_ONION);
144 case SETTING::LAYER_VISIBILITY_THRESHOLD:
145 case SETTING::LAYER_VISIBILITY:
146 setLayerVisibility(static_cast<LayerVisibility>(mPrefs->getInt(SETTING::LAYER_VISIBILITY)));
154 void ScribbleArea::updateToolCursor()
157 updateCanvasCursor();
161 void ScribbleArea::setCurveSmoothing(
int newSmoothingLevel)
163 mCurveSmoothingLevel = newSmoothingLevel / 20.0;
167 void ScribbleArea::setEffect(SETTING e,
bool isOn)
169 mPrefs->set(e, isOn);
176 void ScribbleArea::updateCurrentFrame()
178 if (mEditor->layers()->currentLayer()->type() == Layer::CAMERA) {
179 updateFrame(mEditor->currentFrame());
185 void ScribbleArea::updateFrame(
int frame)
187 Q_ASSERT(frame >= 0);
189 int frameNumber = mEditor->layers()->lastFrameAtFrame(frame);
190 if (frameNumber < 0) {
return; }
192 auto cacheKeyIter = mPixmapCacheKeys.
find(static_cast<unsigned int>(frameNumber));
193 if (cacheKeyIter != mPixmapCacheKeys.
end())
196 unsigned int key = cacheKeyIter.key();
197 mPixmapCacheKeys.
remove(key);
200 updateOnionSkinsAround(frame);
214 void ScribbleArea::updateOnionSkinsAround(
int frameNumber)
216 if (frameNumber < 0) {
return; }
218 bool isOnionAbsolute = mPrefs->getString(SETTING::ONION_TYPE) ==
"absolute";
219 Layer *layer = mEditor->layers()->currentLayer(0);
224 if (mPrefs->isOn(SETTING::PREV_ONION))
226 int onionFrameNumber = frameNumber;
229 onionFrameNumber = layer->getPreviousFrameNumber(onionFrameNumber + 1,
true);
232 for(
int i = 1; i <= mPrefs->getInt(SETTING::ONION_PREV_FRAMES_NUM); i++)
234 onionFrameNumber = layer->getNextFrameNumber(onionFrameNumber, isOnionAbsolute);
235 if (onionFrameNumber < 0)
break;
237 auto cacheKeyIter = mPixmapCacheKeys.
find(static_cast<unsigned int>(onionFrameNumber));
238 if (cacheKeyIter != mPixmapCacheKeys.
end())
241 unsigned int key = cacheKeyIter.key();
242 mPixmapCacheKeys.
remove(key);
247 if (mPrefs->isOn(SETTING::NEXT_ONION))
249 int onionFrameNumber = frameNumber;
251 for(
int i = 1; i <= mPrefs->getInt(SETTING::ONION_NEXT_FRAMES_NUM); i++)
253 onionFrameNumber = layer->getPreviousFrameNumber(onionFrameNumber, isOnionAbsolute);
254 if (onionFrameNumber < 0)
break;
256 auto cacheKeyIter = mPixmapCacheKeys.
find(static_cast<unsigned int>(onionFrameNumber));
257 if (cacheKeyIter != mPixmapCacheKeys.
end())
260 unsigned int key = cacheKeyIter.key();
261 mPixmapCacheKeys.
remove(key);
267 void ScribbleArea::updateAllFrames()
270 mPixmapCacheKeys.
clear();
276 void ScribbleArea::updateAllVectorLayersAtCurrentFrame()
278 updateAllVectorLayersAt(mEditor->currentFrame());
281 void ScribbleArea::updateAllVectorLayersAt(
int frameNumber)
283 for (
int i = 0; i < mEditor->object()->getLayerCount(); i++)
285 Layer* layer = mEditor->object()->getLayer(i);
286 if (layer->type() == Layer::VECTOR)
288 VectorImage* vectorImage = currentVectorImage(layer);
289 if (vectorImage !=
nullptr)
291 vectorImage->modification();
295 updateFrame(frameNumber);
298 void ScribbleArea::setModified(
int layerNumber,
int frameNumber)
300 Layer* layer = mEditor->object()->getLayer(layerNumber);
303 layer->setModified(frameNumber,
true);
304 emit modification(layerNumber);
305 updateFrame(frameNumber);
309 void ScribbleArea::setAllDirty()
311 mCanvasPainter.resetLayerCache();
314 bool ScribbleArea::event(
QEvent *event)
326 void ScribbleArea::keyPressEvent(
QKeyEvent *event)
331 mKeyboardInUse =
true;
333 if (isPointerInUse()) {
return; }
334 if (mInstantTool) {
return; }
336 if (currentTool()->keyPressEvent(event))
344 setTemporaryTool(ERASER);
350 auto selectMan = mEditor->select();
351 bool isSomethingSelected = selectMan->somethingSelected();
352 if (isSomethingSelected) {
353 keyEventForSelection(event);
359 void ScribbleArea::keyEventForSelection(
QKeyEvent* event)
361 auto selectMan = mEditor->select();
362 switch (event->
key())
365 selectMan->translate(
QPointF(1, 0));
366 paintTransformedSelection();
369 selectMan->translate(
QPointF(-1, 0));
370 paintTransformedSelection();
373 selectMan->translate(
QPointF(0, -1));
374 paintTransformedSelection();
377 selectMan->translate(
QPointF(0, 1));
378 paintTransformedSelection();
381 applyTransformedSelection();
382 mEditor->deselectAll();
385 mEditor->deselectAll();
386 cancelTransformedSelection();
390 mEditor->deselectAll();
393 setTemporaryTool(HAND);
400 void ScribbleArea::keyEvent(
QKeyEvent* event)
402 switch (event->
key())
405 mEditor->scrubForward();
409 mEditor->scrubBackward();
413 mEditor->layers()->gotoNextLayer();
417 mEditor->layers()->gotoPreviouslayer();
424 setTemporaryTool(HAND);
431 void ScribbleArea::keyReleaseEvent(
QKeyEvent *event)
439 mKeyboardInUse =
false;
441 if (isPointerInUse()) {
return; }
445 currentTool()->keyReleaseEvent(event);
449 if (currentTool()->keyReleaseEvent(event))
461 if (isPointerInUse())
return;
463 Layer* layer = mEditor->layers()->currentLayer();
464 if (layer->type() == Layer::CAMERA && !layer->visible())
466 showLayerNotVisibleWarning();
470 const QPoint pixels =
event->pixelDelta();
471 const QPoint angle =
event->angleDelta();
472 const QPointF offset = mEditor->view()->mapScreenToCanvas(event->
posF());
474 const qreal currentScale = mEditor->view()->scaling();
480 const int delta = pixels.
y();
481 const qreal newScale = currentScale * (1 + (delta * 0.01));
482 mEditor->view()->scaleWithOffset(newScale, offset);
486 const int delta = angle.
y();
488 const qreal newScale = currentScale * std::pow(100, delta / (12.0 * 120));
489 mEditor->view()->scaleWithOffset(newScale, offset);
491 updateCanvasCursor();
501 editor()->tools()->tabletSwitchToEraser();
505 editor()->tools()->tabletRestorePrevTool();
511 mStrokeManager->pointerPressEvent(&event);
512 mStrokeManager->setTabletInUse(
true);
515 mIsFirstClick =
false;
516 mDoubleClickTimer->
start();
517 pointerPressEvent(&event);
521 qreal distance =
QLineF(currentTool()->getCurrentPressPoint(), currentTool()->getLastPressPoint()).
length();
523 if (mDoubleClickMillis <= DOUBLE_CLICK_THRESHOLD && distance < 5.0) {
524 currentTool()->pointerDoubleClickEvent(&event);
529 pointerPressEvent(&event);
532 mTabletInUse =
event.isAccepted();
538 mStrokeManager->pointerMoveEvent(&event);
539 pointerMoveEvent(&event);
546 mStrokeManager->pointerReleaseEvent(&event);
547 pointerReleaseEvent(&event);
548 mStrokeManager->setTabletInUse(
false);
549 mTabletInUse =
false;
553 #if defined Q_OS_LINUX
569 void ScribbleArea::pointerPressEvent(
PointerEvent* event)
571 bool isCameraLayer = mEditor->layers()->currentLayer()->type() == Layer::CAMERA;
574 Layer* layer = mEditor->layers()->currentLayer();
575 if (!layer->visible())
587 setTemporaryTool(HAND);
588 getTool(HAND)->pointerPressEvent(event);
592 if (isPressed && mQuickSizing)
595 if (currentTool()->startAdjusting(event->
modifiers(), 1))
603 currentTool()->pointerPressEvent(event);
607 void ScribbleArea::pointerMoveEvent(
PointerEvent* event)
609 updateCanvasCursor();
615 if (currentTool()->isAdjusting())
617 currentTool()->adjustCursor(event->
modifiers());
625 getTool(HAND)->pointerMoveEvent(event);
629 currentTool()->pointerMoveEvent(event);
632 void ScribbleArea::pointerReleaseEvent(
PointerEvent* event)
634 if (currentTool()->isAdjusting())
636 currentTool()->stopAdjusting();
637 mEditor->tools()->setWidth(static_cast<float>(currentTool()->properties.width));
643 getTool(HAND)->pointerReleaseEvent(event);
644 mMouseRightButtonInUse =
false;
649 currentTool()->pointerReleaseEvent(event);
652 if (mInstantTool && !mKeyboardInUse)
658 void ScribbleArea::handleDoubleClick()
660 mDoubleClickMillis += 100;
662 if (mDoubleClickMillis >= DOUBLE_CLICK_THRESHOLD)
664 mDoubleClickMillis = 0;
665 mIsFirstClick =
true;
666 mDoubleClickTimer->
stop();
670 bool ScribbleArea::isLayerPaintable()
const
672 Layer* layer = mEditor->layers()->currentLayer();
673 if (layer ==
nullptr) {
return false; }
675 return layer->type() == Layer::BITMAP || layer->type() == Layer::VECTOR;
688 mStrokeManager->pointerPressEvent(&event);
690 pointerPressEvent(&event);
691 mMouseInUse =
event.isAccepted();
698 mStrokeManager->pointerMoveEvent(&event);
700 pointerMoveEvent(&event);
703 void ScribbleArea::mouseReleaseEvent(
QMouseEvent* e)
707 mStrokeManager->pointerReleaseEvent(&event);
709 pointerReleaseEvent(&event);
713 void ScribbleArea::mouseDoubleClickEvent(
QMouseEvent* e)
715 if (mStrokeManager->isTabletInUse()) { e->
ignore();
return; }
717 mStrokeManager->pointerPressEvent(&event);
719 currentTool()->pointerDoubleClickEvent(&event);
728 mEditor->view()->setCanvasSize(
size());
732 void ScribbleArea::showLayerNotVisibleWarning()
735 tr(
"You are trying to modify a hidden layer! Please select another layer (or make the current layer visible)."),
740 void ScribbleArea::paintBitmapBuffer()
744 Q_ASSERT(layer->type() == Layer::BITMAP);
746 int frameNumber = mEditor->currentFrame();
750 if (layer->getLastKeyFrameAtPosition(frameNumber) ==
nullptr)
752 updateCurrentFrame();
757 BitmapImage* targetImage = currentBitmapImage(layer);
758 if (targetImage !=
nullptr)
761 switch (currentTool()->type())
769 if (getTool(currentTool()->type())->properties.preserveAlpha)
777 targetImage->paste(mBufferImg, cm);
780 QRect rect = mEditor->view()->mapCanvasToScreen(mBufferImg->bounds()).toRect();
782 drawCanvas(frameNumber, rect.
adjusted(-1, -1, 1, 1));
786 updateFrame(frameNumber);
787 layer->setModified(frameNumber,
true);
792 void ScribbleArea::paintBitmapBufferRect(
const QRect& rect)
794 if (mEditor->playback()->isPlaying())
796 Layer* layer = mEditor->layers()->currentLayer();
799 BitmapImage* targetImage = currentBitmapImage(layer);
801 if (targetImage !=
nullptr)
804 switch (currentTool()->type())
812 if (getTool(currentTool()->type())->properties.preserveAlpha)
820 targetImage->paste(mBufferImg, cm);
826 int frameNumber = mEditor->currentFrame();
827 layer->setModified(frameNumber,
true);
829 updateFrame(frameNumber);
831 drawCanvas(frameNumber, rect.
adjusted(-1, -1, 1, 1));
836 void ScribbleArea::clearBitmapBuffer()
843 mBufferImg->drawLine(P1, P2, pen, cm, mPrefs->isOn(SETTING::ANTIALIAS));
848 mBufferImg->drawPath(path, pen, brush, cm, mPrefs->isOn(SETTING::ANTIALIAS));
851 void ScribbleArea::refreshBitmap(
const QRectF& rect,
int rad)
857 void ScribbleArea::refreshVector(
const QRectF& rect,
int rad)
868 void ScribbleArea::paintCanvasCursor(
QPainter& painter)
871 QPointF mousePos = currentTool()->isAdjusting() ? currentTool()->getCurrentPressPoint() : currentTool()->getCurrentPoint();
872 int centerCal = mCursorImg.
width() / 2;
874 mTransformedCursorPos = view.
map(mousePos);
880 mCursorCenterPos.
setX(centerCal);
881 mCursorCenterPos.
setY(centerCal);
883 painter.
drawPixmap(
QPoint(static_cast<int>(mTransformedCursorPos.
x() - mCursorCenterPos.
x()),
884 static_cast<int>(mTransformedCursorPos.
y() - mCursorCenterPos.
y())),
890 mCursorCenterPos.
setX(centerCal);
891 mCursorCenterPos.
setY(centerCal);
894 void ScribbleArea::updateCanvasCursor()
896 float scalingFac = mEditor->view()->scaling();
897 qreal brushWidth = currentTool()->properties.width;
898 qreal brushFeather = currentTool()->properties.feather;
899 if (currentTool()->isAdjusting())
903 else if (mEditor->preference()->isOn(SETTING::DOTTED_CURSOR))
905 bool useFeather = currentTool()->properties.useFeather;
906 mCursorImg = currentTool()->
canvasCursor(static_cast<float>(brushWidth), static_cast<float>(brushFeather), useFeather, scalingFac,
width());
914 QPoint translatedPos =
QPoint(static_cast<int>(mTransformedCursorPos.
x() - mCursorCenterPos.
x()),
915 static_cast<int>(mTransformedCursorPos.
y() - mCursorCenterPos.
y()));
924 auto layer = mEditor->layers()->currentLayer();
926 if (!layer || !layer->isPaintable())
931 int frameNumber = mEditor->currentFrame();
932 auto previousKeyFrame = layer->getLastKeyFrameAtPosition(frameNumber);
934 if (layer->getKeyFrameAt(frameNumber) ==
nullptr)
937 int action = mPrefs->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION);
941 case KEEP_DRAWING_ON_PREVIOUS_KEY:
943 if (previousKeyFrame ==
nullptr) {
944 mEditor->addNewKey();
948 case DUPLICATE_PREVIOUS_KEY:
950 if (previousKeyFrame)
952 KeyFrame* dupKey = previousKeyFrame->clone();
953 layer->addKeyFrame(frameNumber, dupKey);
954 mEditor->scrubTo(frameNumber);
962 mEditor->addNewKey();
965 drawCanvas(frameNumber, mCanvas.
rect());
975 if (!currentTool()->isActive())
978 int curIndex = mEditor->currentFrame();
979 int frameNumber = mEditor->layers()->lastFrameAtFrame(curIndex);
983 drawCanvas(curIndex, event->
rect());
987 auto cacheKeyIter = mPixmapCacheKeys.
find(static_cast<unsigned>(frameNumber));
991 drawCanvas(mEditor->currentFrame(),
event->rect());
1000 prepCanvas(mEditor->currentFrame(),
event->rect());
1001 mCanvasPainter.paintCached();
1004 if (currentTool()->type() == MOVE)
1006 Layer* layer = mEditor->layers()->currentLayer();
1008 if (layer->type() == Layer::VECTOR)
1010 VectorImage* vectorImage = currentVectorImage(layer);
1011 if (vectorImage !=
nullptr)
1013 vectorImage->setModified(
true);
1024 Layer* layer = mEditor->layers()->currentLayer();
1026 if (!editor()->playback()->isPlaying())
1028 if (layer->type() == Layer::VECTOR)
1030 VectorImage* vectorImage = currentVectorImage(layer);
1031 if (vectorImage !=
nullptr)
1033 switch (currentTool()->type())
1038 auto selectMan = mEditor->select();
1047 color =
QColor(200, 200, 200);
1050 for (
int k = 0; k < vectorSelection.curve.
size(); k++)
1052 int curveNumber = vectorSelection.curve.
at(k);
1054 for (
int vertexNumber = -1; vertexNumber < vectorImage->
getCurveSize(curveNumber); vertexNumber++)
1057 QRectF rectangle(mEditor->view()->mapCanvasToScreen(vertexPoint) -
QPointF(3.0, 3.0),
QSizeF(7, 7));
1065 color =
QColor(100, 100, 255);
1067 for (
int k = 0; k < vectorSelection.vertex.
size(); k++)
1069 VertexRef vertexRef = vectorSelection.vertex.
at(k);
1075 color =
QColor(255, 0, 0);
1078 if (vectorSelection.curve.
size() > 0)
1080 for (
int k = 0; k < closestVertices.
size(); k++)
1100 paintCanvasCursor(painter);
1102 mCanvasPainter.renderGrid(painter);
1103 mCanvasPainter.renderOverlays(painter);
1106 if (mEditor->select()->somethingSelected())
1108 paintSelectionVisuals(painter);
1123 void ScribbleArea::paintSelectionVisuals(
QPainter &painter)
1125 Object*
object = mEditor->object();
1127 auto selectMan = mEditor->select();
1128 selectMan->updatePolygons();
1130 if (selectMan->currentSelectionPolygonF().isEmpty()) {
return; }
1131 if (selectMan->currentSelectionPolygonF().count() < 4) {
return; }
1133 QPolygonF lastSelectionPolygon = editor()->view()->mapPolygonToScreen(selectMan->lastSelectionPolygonF());
1134 QPolygonF currentSelectionPolygon = selectMan->currentSelectionPolygonF();
1135 if (mEditor->layers()->currentLayer()->type() == Layer::BITMAP)
1137 currentSelectionPolygon = currentSelectionPolygon.
toPolygon();
1139 currentSelectionPolygon = editor()->view()->mapPolygonToScreen(currentSelectionPolygon);
1142 mSelectionPainter.paint(painter,
object, mEditor->currentLayerIndex(), currentTool(), params);
1147 Q_ASSERT(layer->type() == Layer::BITMAP);
1148 auto bitmapLayer =
static_cast<LayerBitmap*
>(layer);
1149 return bitmapLayer->getLastBitmapImageAtFrame(mEditor->currentFrame());
1154 Q_ASSERT(layer->type() == Layer::VECTOR);
1155 auto vectorLayer =
static_cast<LayerVector*
>(layer);
1156 return vectorLayer->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
1159 void ScribbleArea::prepCanvas(
int frame,
QRect rect)
1161 Object*
object = mEditor->object();
1164 o.bPrevOnionSkin = mPrefs->isOn(SETTING::PREV_ONION);
1165 o.bNextOnionSkin = mPrefs->isOn(SETTING::NEXT_ONION);
1166 o.bColorizePrevOnion = mPrefs->isOn(SETTING::ONION_RED);
1167 o.bColorizeNextOnion = mPrefs->isOn(SETTING::ONION_BLUE);
1168 o.nPrevOnionSkinCount = mPrefs->getInt(SETTING::ONION_PREV_FRAMES_NUM);
1169 o.nNextOnionSkinCount = mPrefs->getInt(SETTING::ONION_NEXT_FRAMES_NUM);
1170 o.fOnionSkinMaxOpacity = mPrefs->getInt(SETTING::ONION_MAX_OPACITY);
1171 o.fOnionSkinMinOpacity = mPrefs->getInt(SETTING::ONION_MIN_OPACITY);
1172 o.bAntiAlias = mPrefs->isOn(SETTING::ANTIALIAS);
1173 o.bGrid = mPrefs->isOn(SETTING::GRID);
1174 o.nGridSizeW = mPrefs->getInt(SETTING::GRID_SIZE_W);
1175 o.nGridSizeH = mPrefs->getInt(SETTING::GRID_SIZE_H);
1176 o.bCenter = mPrefs->isOn(SETTING::OVERLAY_CENTER);
1177 o.bThirds = mPrefs->isOn(SETTING::OVERLAY_THIRDS);
1178 o.bGoldenRatio = mPrefs->isOn(SETTING::OVERLAY_GOLDEN);
1179 o.bSafeArea = mPrefs->isOn(SETTING::OVERLAY_SAFE);
1180 o.bActionSafe = mPrefs->isOn(SETTING::ACTION_SAFE_ON);
1181 o.nActionSafe = mPrefs->getInt(SETTING::ACTION_SAFE);
1182 o.bShowSafeAreaHelperText = mPrefs->isOn(SETTING::OVERLAY_SAFE_HELPER_TEXT_ON);
1183 o.bTitleSafe = mPrefs->isOn(SETTING::TITLE_SAFE_ON);
1184 o.nTitleSafe = mPrefs->getInt(SETTING::TITLE_SAFE);
1186 o.bThinLines = mPrefs->isOn(SETTING::INVISIBLE_LINES);
1187 o.bOutlines = mPrefs->isOn(SETTING::OUTLINES);
1188 o.eLayerVisibility = mLayerVisibility;
1189 o.fLayerVisibilityThreshold = mPrefs->getFloat(SETTING::LAYER_VISIBILITY_THRESHOLD);
1190 o.bIsOnionAbsolute = (mPrefs->getString(SETTING::ONION_TYPE) ==
"absolute");
1191 o.scaling = mEditor->view()->scaling();
1192 o.onionWhilePlayback = mPrefs->getInt(SETTING::ONION_WHILE_PLAYBACK);
1193 o.isPlaying = mEditor->playback()->isPlaying() ?
true :
false;
1195 mCanvasPainter.setOptions(o);
1197 mCanvasPainter.setCanvas(&mCanvas);
1200 mCanvasPainter.setViewTransform(vm->getView(), vm->getViewInverse());
1202 mCanvasPainter.setPaintSettings(
object, mEditor->layers()->currentLayerIndex(), frame,
rect, mBufferImg);
1205 void ScribbleArea::drawCanvas(
int frame,
QRect rect)
1208 prepCanvas(frame, rect);
1209 mCanvasPainter.paint();
1212 void ScribbleArea::setGaussianGradient(
QGradient &gradient,
QColor color, qreal opacity, qreal offset)
1214 if (offset < 0) { offset = 0; }
1215 if (offset > 100) { offset = 100; }
1217 int r = color.
red();
1218 int g = color.
green();
1219 int b = color.
blue();
1220 qreal a = color.
alphaF();
1222 int mainColorAlpha = qRound(a * 255 * opacity);
1225 int alphaAdded = qRound((mainColorAlpha * offset) / 100);
1229 gradient.
setColorAt(1.0 - (offset / 100.0),
QColor(r, g, b, mainColorAlpha - alphaAdded));
1232 void ScribbleArea::drawPen(
QPointF thePoint, qreal brushWidth,
QColor fillColor,
bool useAA)
1234 QRectF rectangle(thePoint.
x() - 0.5 * brushWidth, thePoint.
y() - 0.5 * brushWidth, brushWidth, brushWidth);
1240 void ScribbleArea::drawPencil(
QPointF thePoint, qreal brushWidth, qreal fixedBrushFeather,
QColor fillColor, qreal opacity)
1242 drawBrush(thePoint, brushWidth, fixedBrushFeather, fillColor, opacity,
true);
1245 void ScribbleArea::drawBrush(
QPointF thePoint, qreal brushWidth, qreal mOffset,
QColor fillColor, qreal opacity,
bool usingFeather,
bool useAA)
1247 QRectF rectangle(thePoint.
x() - 0.5 * brushWidth, thePoint.
y() - 0.5 * brushWidth, brushWidth, brushWidth);
1252 setGaussianGradient(radialGrad, fillColor, opacity, mOffset);
1254 mBufferImg->drawEllipse(rectangle,
Qt::NoPen, radialGrad,
1264 void ScribbleArea::flipSelection(
bool flipVertical)
1267 paintTransformedSelection();
1270 void ScribbleArea::blurBrush(
BitmapImage *bmiSource_,
QPointF srcPoint_,
QPointF thePoint_, qreal brushWidth_, qreal mOffset_, qreal opacity_)
1273 setGaussianGradient(radialGrad,
QColor(255, 255, 255, 127), opacity_, mOffset_);
1275 QRectF srcRect(srcPoint_.
x() - 0.5 * brushWidth_, srcPoint_.
y() - 0.5 * brushWidth_, brushWidth_, brushWidth_);
1276 QRectF trgRect(thePoint_.
x() - 0.5 * brushWidth_, thePoint_.
y() - 0.5 * brushWidth_, brushWidth_, brushWidth_);
1278 BitmapImage bmiSrcClip = bmiSource_->copy(srcRect.toAlignedRect());
1282 bmiSrcClip.bounds().moveTo(trgRect.topLeft().toPoint());
1284 mBufferImg->paste(&bmiTmpClip);
1287 void ScribbleArea::liquifyBrush(
BitmapImage *bmiSource_,
QPointF srcPoint_,
QPointF thePoint_, qreal brushWidth_, qreal mOffset_, qreal opacity_)
1289 QPointF delta = (thePoint_ - srcPoint_);
1290 QRectF trgRect(thePoint_.
x() - 0.5 * brushWidth_, thePoint_.
y() - 0.5 * brushWidth_, brushWidth_, brushWidth_);
1293 setGaussianGradient(radialGrad,
QColor(255, 255, 255, 255), opacity_, mOffset_);
1300 qreal factor, factorGrad;
1302 for (
int yb = bmiTmpClip.top(); yb < bmiTmpClip.bottom(); yb++)
1304 for (
int xb = bmiTmpClip.left(); xb < bmiTmpClip.right(); xb++)
1307 color.
setRgba(bmiTmpClip.pixel(xb, yb));
1308 factorGrad = color.
alphaF();
1310 int xa = xb - factorGrad * delta.
x();
1311 int ya = yb - factorGrad * delta.
y();
1313 color.
setRgba(bmiSource_->pixel(xa, ya));
1328 bmiTmpClip.setPixel(xb, yb, color.
rgba());
1332 bmiTmpClip.setPixel(xb, yb, qRgba(255, 255, 255, 0));
1336 mBufferImg->paste(&bmiTmpClip);
1345 mBufferImg->clear();
1354 QRectF ScribbleArea::getCameraRect()
1356 return mCanvasPainter.getCameraRect();
1359 QPointF ScribbleArea::getCentralPoint()
1364 void ScribbleArea::paintTransformedSelection()
1366 Layer* layer = mEditor->layers()->currentLayer();
1367 if (layer ==
nullptr) {
return; }
1369 auto selectMan = mEditor->select();
1370 if (selectMan->somethingSelected())
1372 if (layer->type() == Layer::BITMAP)
1374 mCanvasPainter.setTransformedSelection(selectMan->mySelectionRect().toRect(), selectMan->selectionTransform());
1376 else if (layer->type() == Layer::VECTOR)
1379 VectorImage* vectorImage = currentVectorImage(layer);
1380 if (vectorImage ==
nullptr) {
return; }
1384 setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
1389 void ScribbleArea::applySelectionChanges()
1393 applyTransformedSelection();
1395 auto selectMan = mEditor->select();
1398 if (!selectMan->myTempTransformedSelectionRect().isValid())
1400 const QRectF& normalizedRect = selectMan->myTempTransformedSelectionRect().
normalized();
1401 selectMan->setTempTransformedSelectionRect(normalizedRect);
1403 selectMan->setSelection(selectMan->myTempTransformedSelectionRect(),
false);
1404 paintTransformedSelection();
1407 selectMan->calculateSelectionTransformation();
1410 applyTransformedSelection();
1413 void ScribbleArea::applyTransformedSelection()
1415 mCanvasPainter.ignoreTransformedSelection();
1417 Layer* layer = mEditor->layers()->currentLayer();
1418 if (layer ==
nullptr) {
return; }
1420 auto selectMan = mEditor->select();
1421 if (selectMan->somethingSelected())
1423 if (selectMan->mySelectionRect().isEmpty() || selectMan->selectionTransform().isIdentity()) {
return; }
1425 if (layer->type() == Layer::BITMAP)
1428 BitmapImage* bitmapImage = currentBitmapImage(layer);
1429 if (bitmapImage ==
nullptr) {
return; }
1430 BitmapImage transformedImage = bitmapImage->transformed(selectMan->mySelectionRect().toRect(), selectMan->selectionTransform(),
true);
1432 bitmapImage->clear(selectMan->mySelectionRect());
1435 else if (layer->type() == Layer::VECTOR)
1440 VectorImage* vectorImage = currentVectorImage(layer);
1441 if (vectorImage ==
nullptr) {
return; }
1443 selectMan->setSelection(selectMan->myTempTransformedSelectionRect(),
false);
1446 setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
1449 updateCurrentFrame();
1452 void ScribbleArea::cancelTransformedSelection()
1454 mCanvasPainter.ignoreTransformedSelection();
1456 auto selectMan = mEditor->select();
1457 if (selectMan->somethingSelected())
1459 Layer* layer = mEditor->layers()->currentLayer();
1460 if (layer ==
nullptr) {
return; }
1462 if (layer->type() == Layer::VECTOR)
1464 VectorImage* vectorImage = currentVectorImage(layer);
1465 if (vectorImage !=
nullptr)
1471 mEditor->select()->setSelection(selectMan->mySelectionRect(),
false);
1473 selectMan->resetSelectionProperties();
1477 void ScribbleArea::displaySelectionProperties()
1479 Layer* layer = mEditor->layers()->currentLayer();
1480 if (layer ==
nullptr) {
return; }
1481 if (layer->type() == Layer::VECTOR)
1483 VectorImage* vectorImage = currentVectorImage(layer);
1484 if (vectorImage ==
nullptr) {
return; }
1486 if (currentTool()->type() == MOVE)
1489 if (selectedCurve != -1)
1491 mEditor->tools()->setWidth(vectorImage->curve(selectedCurve).getWidth());
1492 mEditor->tools()->setFeather(vectorImage->curve(selectedCurve).getFeather());
1493 mEditor->tools()->setInvisibility(vectorImage->curve(selectedCurve).isInvisible());
1494 mEditor->tools()->setPressure(vectorImage->curve(selectedCurve).getVariableWidth());
1495 mEditor->color()->setColorNumber(vectorImage->curve(selectedCurve).getColorNumber());
1499 if (selectedArea != -1)
1501 mEditor->color()->setColorNumber(vectorImage->mArea[selectedArea].mColorNumber);
1507 void ScribbleArea::toggleThinLines()
1509 bool previousValue = mPrefs->isOn(SETTING::INVISIBLE_LINES);
1510 setEffect(SETTING::INVISIBLE_LINES, !previousValue);
1513 void ScribbleArea::toggleOutlines()
1515 mIsSimplified = !mIsSimplified;
1516 setEffect(SETTING::OUTLINES, mIsSimplified);
1519 void ScribbleArea::setLayerVisibility(LayerVisibility visibility)
1521 mLayerVisibility = visibility;
1522 mPrefs->set(SETTING::LAYER_VISIBILITY, static_cast<int>(mLayerVisibility));
1526 void ScribbleArea::increaseLayerVisibilityIndex()
1529 mPrefs->set(SETTING::LAYER_VISIBILITY, static_cast<int>(mLayerVisibility));
1533 void ScribbleArea::decreaseLayerVisibilityIndex()
1536 mPrefs->set(SETTING::LAYER_VISIBILITY, static_cast<int>(mLayerVisibility));
1543 BaseTool* ScribbleArea::currentTool()
const
1545 return editor()->tools()->currentTool();
1548 BaseTool* ScribbleArea::getTool(ToolType eToolType)
1550 return editor()->tools()->getTool(eToolType);
1554 void ScribbleArea::setCurrentTool(ToolType eToolMode)
1556 if (currentTool() !=
nullptr && eToolMode != currentTool()->type())
1559 if (BaseTool::TypeName(eToolMode) ==
"")
1566 if (currentTool()->type() == MOVE)
1568 paintTransformedSelection();
1569 mEditor->deselectAll();
1571 else if (currentTool()->type() == POLYLINE)
1573 mEditor->deselectAll();
1577 mPrevToolType = currentTool()->type();
1581 updateCanvasCursor();
1585 void ScribbleArea::setTemporaryTool(ToolType eToolMode)
1589 if (!mInstantTool && currentTool()->type() != eToolMode)
1591 mInstantTool =
true;
1592 mPrevTemporalToolType = currentTool()->type();
1593 editor()->tools()->setCurrentTool(eToolMode);
1597 void ScribbleArea::deleteSelection()
1599 auto selectMan = mEditor->select();
1600 if (selectMan->somethingSelected())
1602 Layer* layer = mEditor->layers()->currentLayer();
1603 if (layer ==
nullptr) {
return; }
1607 mEditor->backup(
tr(
"Delete Selection",
"Undo Step: clear the selection area."));
1609 selectMan->clearCurves();
1610 if (layer->type() == Layer::VECTOR)
1612 VectorImage* vectorImage = currentVectorImage(layer);
1613 Q_CHECK_PTR(vectorImage);
1616 else if (layer->type() == Layer::BITMAP)
1618 BitmapImage* bitmapImage = currentBitmapImage(layer);
1619 Q_CHECK_PTR(bitmapImage);
1620 bitmapImage->clear(selectMan->mySelectionRect());
1626 void ScribbleArea::clearImage()
1628 Layer* layer = mEditor->layers()->currentLayer();
1629 if (layer ==
nullptr) {
return; }
1631 if (layer->type() == Layer::VECTOR)
1633 mEditor->backup(
tr(
"Clear Image",
"Undo step text"));
1635 VectorImage* vectorImage = currentVectorImage(layer);
1636 if (vectorImage !=
nullptr)
1638 vectorImage->
clear();
1640 mEditor->select()->clearCurves();
1641 mEditor->select()->clearVertices();
1643 else if (layer->type() == Layer::BITMAP)
1645 mEditor->backup(
tr(
"Clear Image",
"Undo step text"));
1647 BitmapImage* bitmapImage = currentBitmapImage(layer);
1648 if (bitmapImage ==
nullptr)
return;
1649 bitmapImage->clear();
1655 setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
1658 void ScribbleArea::setPrevTool()
1662 editor()->tools()->setCurrentTool(mPrevTemporalToolType);
1663 mInstantTool =
false;
1667 void ScribbleArea::paletteColorChanged(
QColor color)
1670 updateAllVectorLayersAtCurrentFrame();
1676 if (errorType == 1) { message =
tr(
"There is a gap in your drawing (or maybe you have zoomed too much)."); }
1677 if (errorType == 2 || errorType == 3)
1679 message =
tr(
"Sorry! This doesn't always work."
1680 "Please try again (zoom a bit, click at another location... )<br>"
1681 "if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.).");
1684 if (errorType == 1) { error =
tr(
"Out of bound.",
"Bucket tool fill error message"); }
1685 if (errorType == 2) { error =
tr(
"Could not find a closed path.",
"Bucket tool fill error message"); }
1686 if (errorType == 3) { error =
tr(
"Could not find the root index.",
"Bucket tool fill error message"); }
1688 mEditor->deselectAll();
1693 return mPrefs->isOn(SETTING::PREV_ONION) ||
1694 mPrefs->isOn(SETTING::NEXT_ONION) ||
1695 getLayerVisibility() != LayerVisibility::ALL;
void setInterval(int msec)
QRectF boundingRect() const const
Qt::KeyboardModifiers modifiers() const const
QPolygon toPolygon() const const
int getFirstSelectedCurve()
VectorImage::getFirstSelectedCurve.
QEvent::Type type() const const
Qt::KeyboardModifiers modifiers() const
Returns the modifier created by keyboard while a device was in use.
QRect toRect() const const
qreal alphaF() const const
void setRenderHint(QPainter::RenderHint hint, bool on)
int getCurveSize(int curveNumber)
VectorImage::getCurveSize.
void fill(const QColor &color)
void remove(const QString &key)
void clear()
VectorImage::clear.
void setColorAt(qreal position, const QColor &color)
const T & at(int i) const const
bool isAutoRepeat() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
const QRect & rect() const const
void drawRect(const QRectF &rectangle)
void setCacheLimit(int n)
qreal length() const const
void updateAllFramesIfNeeded()
Check if the cache should be invalidated for all frames since the last paint operation.
int getFirstSelectedArea()
VectorImage::getFirstSelectedArea.
void handleDrawingOnEmptyFrame()
Call this when starting to use a paint tool.
const QPointF & posF() const const
void setPen(const QColor &color)
QRectF normalized() const const
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
void setObjectName(const QString &name)
QPointF getVertex(int curveNumber, int vertexNumber)
VectorImage::getVertex.
void setBrush(const QBrush &brush)
QRect translated(int dx, int dy) const const
QRect adjusted(int dx1, int dy1, int dx2, int dy2) const const
Qt::MouseButtons buttons() const
Returns Qt::MouseButtons()
bool isAffectedByActiveLayer() const
Check if the content of the canvas depends on the active layer.
bool contains(const QRect &rectangle, bool proper) const const
void setSelectionTransformation(QTransform transform)
VectorImage::setSelectionTransformation.
bool isNull() const const
QPoint toPoint() const const
void setWorldMatrixEnabled(bool enable)
QPixmap * find(const QString &key)
Qt::MouseButton button() const
Returns Qt::MouseButton()
void applySelectionTransformation()
VectorImage::applySelectionTransformation.
QRectF adjusted(qreal dx1, qreal dy1, qreal dx2, qreal dy2) const const
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
void flipSelection(bool flipVertical)
ScribbleArea::flipSelection flip selection along the X or Y axis.
bool insert(const QString &key, const QPixmap &pixmap)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QMap::iterator find(const Key &key)
void deleteSelection()
VectorImage::deleteSelection.
int remove(const Key &key)