18#include "scribblearea.h"
21#include <QGuiApplication>
23#include <QPixmapCache>
26#include "pointerevent.h"
27#include "beziercurve.h"
30#include "layerbitmap.h"
31#include "layervector.h"
32#include "layercamera.h"
33#include "bitmapimage.h"
34#include "vectorimage.h"
38#include "onionskinpainteroptions.h"
40#include "colormanager.h"
41#include "toolmanager.h"
42#include "layermanager.h"
43#include "playbackmanager.h"
44#include "viewmanager.h"
45#include "selectionmanager.h"
46#include "overlaymanager.h"
49 mCanvasPainter(mCanvas),
50 mCameraPainter(mCanvas)
52 setObjectName(
"ScribbleArea");
59ScribbleArea::~ScribbleArea()
63bool ScribbleArea::init()
65 mPrefs = mEditor->preference();
66 mDoubleClickTimer =
new QTimer(
this);
67 mMouseFilterTimer =
new QTimer(
this);
69 connect(mPrefs, &PreferenceManager::optionChanged,
this, &ScribbleArea::settingUpdated);
77 connect(mEditor->select(), &SelectionManager::needDeleteSelection,
this, &ScribbleArea::deleteSelection);
79 connect(&mTiledBuffer, &TiledBuffer::tileUpdated,
this, &ScribbleArea::onTileUpdated);
80 connect(&mTiledBuffer, &TiledBuffer::tileCreated,
this, &ScribbleArea::onTileCreated);
85 const int curveSmoothingLevel = mPrefs->getInt(SETTING::CURVE_SMOOTHING);
86 mCurveSmoothingLevel = curveSmoothingLevel / 20.0;
88 mMakeInvisible =
false;
90 mLayerVisibility =
static_cast<LayerVisibility
>(mPrefs->getInt(SETTING::LAYER_VISIBILITY));
92 mDeltaFactor = mEditor->preference()->isOn(SETTING::INVERT_SCROLL_ZOOM_DIRECTION) ? -1 : 1;
95#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
102 mPixmapCacheKeys.
clear();
107void ScribbleArea::settingUpdated(SETTING setting)
111 case SETTING::CURVE_SMOOTHING:
112 setCurveSmoothing(mPrefs->getInt(SETTING::CURVE_SMOOTHING));
114 case SETTING::TOOL_CURSOR:
117 case SETTING::ONION_PREV_FRAMES_NUM:
118 case SETTING::ONION_NEXT_FRAMES_NUM:
119 case SETTING::ONION_MIN_OPACITY:
120 case SETTING::ONION_MAX_OPACITY:
123 case SETTING::ANTIALIAS:
125 case SETTING::GRID_SIZE_W:
126 case SETTING::GRID_SIZE_H:
127 case SETTING::OVERLAY_CENTER:
128 case SETTING::OVERLAY_THIRDS:
129 case SETTING::OVERLAY_GOLDEN:
130 case SETTING::OVERLAY_SAFE:
131 case SETTING::OVERLAY_PERSPECTIVE1:
132 case SETTING::OVERLAY_PERSPECTIVE2:
133 case SETTING::OVERLAY_PERSPECTIVE3:
134 case SETTING::ACTION_SAFE_ON:
135 case SETTING::ACTION_SAFE:
136 case SETTING::TITLE_SAFE_ON:
137 case SETTING::TITLE_SAFE:
138 case SETTING::OVERLAY_SAFE_HELPER_TEXT_ON:
139 case SETTING::PREV_ONION:
140 case SETTING::NEXT_ONION:
141 case SETTING::ONION_BLUE:
142 case SETTING::ONION_RED:
143 case SETTING::INVISIBLE_LINES:
144 case SETTING::OUTLINES:
145 case SETTING::ONION_TYPE:
146 case SETTING::ONION_WHILE_PLAYBACK:
149 case SETTING::ONION_MUTLIPLE_LAYERS:
152 case SETTING::LAYER_VISIBILITY_THRESHOLD:
153 case SETTING::LAYER_VISIBILITY:
154 setLayerVisibility(
static_cast<LayerVisibility
>(mPrefs->getInt(SETTING::LAYER_VISIBILITY)));
156 case SETTING::INVERT_SCROLL_ZOOM_DIRECTION:
157 mDeltaFactor = mEditor->preference()->isOn(SETTING::INVERT_SCROLL_ZOOM_DIRECTION) ? -1 : 1;
165void ScribbleArea::updateToolCursor()
170void ScribbleArea::setCurveSmoothing(
int newSmoothingLevel)
172 mCurveSmoothingLevel = newSmoothingLevel / 20.0;
176void ScribbleArea::setEffect(SETTING e,
bool isOn)
178 mPrefs->set(e, isOn);
187 Q_UNUSED(tiledBuffer);
194 Q_UNUSED(tiledBuffer)
201 if (currentTool()->isActive() && currentTool()->isDrawingTool()) {
210 Layer* currentLayer = mEditor->layers()->currentLayer();
221 if (frameNumber < 0) {
return; }
223 bool isOnionAbsolute = mPrefs->getString(SETTING::ONION_TYPE) ==
"absolute";
224 Layer *layer = mEditor->layers()->currentLayer(0);
229 if (mPrefs->isOn(SETTING::PREV_ONION))
231 int onionFrameNumber = frameNumber;
234 onionFrameNumber = layer->getPreviousFrameNumber(onionFrameNumber + 1,
true);
237 for(
int i = 1; i <= mPrefs->getInt(SETTING::ONION_PREV_FRAMES_NUM); i++)
239 onionFrameNumber = layer->getPreviousFrameNumber(onionFrameNumber, isOnionAbsolute);
240 if (onionFrameNumber < 0)
break;
246 if (mPrefs->isOn(SETTING::NEXT_ONION))
248 int onionFrameNumber = frameNumber;
250 for(
int i = 1; i <= mPrefs->getInt(SETTING::ONION_NEXT_FRAMES_NUM); i++)
252 onionFrameNumber = layer->getNextFrameNumber(onionFrameNumber, isOnionAbsolute);
253 if (onionFrameNumber < 0)
break;
262 if (currentTool()->isDrawingTool() && currentTool()->isActive()) {
return; }
265 mPixmapCacheKeys.
clear();
274 auto cacheKeyIter = mPixmapCacheKeys.
find(
static_cast<unsigned int>(frameNumber));
275 if (cacheKeyIter != mPixmapCacheKeys.
end())
278 unsigned int key = cacheKeyIter.key();
279 mPixmapCacheKeys.
remove(key);
285 mCameraPainter.resetCache();
286 mCanvasPainter.resetLayerCache();
294 case ToolPropertyType::CAMERAPATH:
304 int frame = mEditor->currentFrame();
306 prepCameraPainter(frame);
314 int currentFrame = mEditor->currentFrame();
315 if (mPrefs->isOn(SETTING::PREV_ONION) ||
316 mPrefs->isOn(SETTING::NEXT_ONION)) {
320 prepOverlays(currentFrame);
321 prepCameraPainter(currentFrame);
328 Q_UNUSED(frameNumber)
336 if (mPrefs->isOn(SETTING::PREV_ONION) || mPrefs->isOn(SETTING::NEXT_ONION)) {
344 if (mPrefs->isOn(SETTING::PREV_ONION) || mPrefs->isOn(SETTING::NEXT_ONION)) {
364 int currentFrame = mEditor->currentFrame();
379bool ScribbleArea::event(
QEvent *event)
381 bool processed =
false;
384 editor()->tools()->clearTemporaryTool();
388 processed = currentTool()->enterEvent(
static_cast<QEnterEvent*
>(event)) || processed;
391 processed = currentTool()->leaveEvent(event) || processed;
401void ScribbleArea::keyPressEvent(
QKeyEvent *event)
406 if (isPointerInUse()) {
return; }
408 if (currentTool()->keyPressEvent(event))
415 editor()->tools()->setTemporaryTool(ERASER, {},
event->modifiers()))
422 auto selectMan = mEditor->select();
423 bool isSomethingSelected = selectMan->somethingSelected();
424 if (isSomethingSelected)
426 keyEventForSelection(event);
434void ScribbleArea::keyEventForSelection(
QKeyEvent* event)
436 auto selectMan = mEditor->select();
437 switch (event->
key())
440 selectMan->translate(
QPointF(1, 0));
441 selectMan->calculateSelectionTransformation();
445 selectMan->translate(
QPointF(-1, 0));
446 selectMan->calculateSelectionTransformation();
450 selectMan->translate(
QPointF(0, -1));
451 selectMan->calculateSelectionTransformation();
455 selectMan->translate(
QPointF(0, 1));
456 selectMan->calculateSelectionTransformation();
460 applyTransformedSelection();
461 mEditor->deselectAll();
464 cancelTransformedSelection();
465 mEditor->deselectAll();
469 mEditor->deselectAll();
483void ScribbleArea::keyEvent(
QKeyEvent* event)
485 switch (event->
key())
488 mEditor->scrubForward();
491 mEditor->scrubBackward();
494 mEditor->layers()->gotoNextLayer();
497 mEditor->layers()->gotoPreviouslayer();
511void ScribbleArea::keyReleaseEvent(
QKeyEvent *event)
519 if (event->
key() == 0)
525 editor()->tools()->tryClearTemporaryTool(
static_cast<Qt::Key>(event->
key()));
528 if (isPointerInUse()) {
return; }
530 if (currentTool()->keyReleaseEvent(event))
542 if (isPointerInUse())
return;
545 const QPoint pixels =
event->pixelDelta();
546 const QPoint angle =
event->angleDelta();
547#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
548 const QPointF offset = mEditor->view()->mapScreenToCanvas(event->
position());
550 const QPointF offset = mEditor->view()->mapScreenToCanvas(event->
posF());
553 const qreal currentScale = mEditor->view()->scaling();
557 if (!isX11 && !pixels.
isNull())
567 const qreal newScale = currentScale * std::pow(100, (delta * mDeltaFactor) / (12.0 * 120));
568 mEditor->view()->scaleAtOffset(newScale, offset);
577#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
578 if (event.pointerType() == QPointingDevice::PointerType::Eraser)
583 editor()->tools()->tabletSwitchToEraser();
587 editor()->tools()->tabletRestorePrevTool();
590 if (event.eventType() == PointerEvent::Press)
595 mIsFirstClick =
false;
596 mDoubleClickTimer->
start();
597 pointerPressEvent(&event);
602 mTabletPressPos = e->
posF();
604 if (mDoubleClickMillis <= DOUBLE_CLICK_THRESHOLD && distance < 5.0) {
605 currentTool()->pointerDoubleClickEvent(&event);
610 pointerPressEvent(&event);
613 mTabletInUse =
event.isAccepted();
615 else if (event.eventType() == PointerEvent::Move)
619 pointerMoveEvent(&event);
622 else if (event.eventType() == PointerEvent::Release)
624 mTabletReleaseMillisAgo = 0;
625 mMouseFilterTimer->
start();
628 pointerReleaseEvent(&event);
629 mTabletInUse =
false;
633#if defined Q_OS_LINUX
649void ScribbleArea::pointerPressEvent(
PointerEvent* event)
651 bool isCameraLayer = mEditor->layers()->currentLayer()->type() == Layer::CAMERA;
654 Layer* layer = mEditor->layers()->currentLayer();
655 if (!layer->visible())
666 editor()->tools()->setTemporaryTool(HAND, event->
buttons()))
668 currentTool()->pointerPressEvent(event);
671 currentTool()->pointerPressEvent(event);
677 currentTool()->pointerMoveEvent(event);
680void ScribbleArea::pointerReleaseEvent(
PointerEvent* event)
682 currentTool()->pointerReleaseEvent(event);
684 editor()->tools()->tryClearTemporaryTool(event->
button());
687void ScribbleArea::handleDoubleClick()
689 mDoubleClickMillis += 100;
691 if (mDoubleClickMillis >= DOUBLE_CLICK_THRESHOLD)
693 mDoubleClickMillis = 0;
694 mIsFirstClick =
true;
695 mDoubleClickTimer->
stop();
699void ScribbleArea::tabletReleaseEventFired()
707 mTabletReleaseMillisAgo += 50;
709 if (mTabletReleaseMillisAgo >= MOUSE_FILTER_THRESHOLD) {
710 mTabletReleaseMillisAgo = 0;
711 mMouseFilterTimer->
stop();
717 if (mTabletInUse || (mMouseFilterTimer->
isActive() && mTabletReleaseMillisAgo < MOUSE_FILTER_THRESHOLD))
724 pointerPressEvent(&event);
725 mMouseInUse =
event.isAccepted();
730 if (mTabletInUse || (mMouseFilterTimer->
isActive() && mTabletReleaseMillisAgo < MOUSE_FILTER_THRESHOLD)) { e->
ignore();
return; }
733 pointerMoveEvent(&event);
736void ScribbleArea::mouseReleaseEvent(
QMouseEvent* e)
738 if (mTabletInUse || (mMouseFilterTimer->
isActive() && mTabletReleaseMillisAgo < MOUSE_FILTER_THRESHOLD)) { e->
ignore();
return; }
741 pointerReleaseEvent(&event);
745void ScribbleArea::mouseDoubleClickEvent(
QMouseEvent* e)
747 if (mTabletInUse) { e->
ignore();
return; }
750 currentTool()->pointerDoubleClickEvent(&event);
759 mEditor->view()->setCanvasSize(
size());
763 mCanvasPainter.reset();
764 mCameraPainter.reset();
767void ScribbleArea::showLayerNotVisibleWarning()
770 tr(
"You are trying to modify a hidden layer! Please select another layer (or make the current layer visible)."),
775void ScribbleArea::paintBitmapBuffer()
779 Q_ASSERT(layer->type() == Layer::BITMAP);
781 int frameNumber = mEditor->currentFrame();
785 if (layer->getLastKeyFrameAtPosition(frameNumber) ==
nullptr)
791 BitmapImage* targetImage = currentBitmapImage(layer);
792 if (targetImage !=
nullptr)
795 switch (currentTool()->type())
803 if (currentTool()->properties.preserveAlpha)
811 targetImage->paste(&mTiledBuffer, cm);
814 QRect rect = mEditor->view()->mapCanvasToScreen(mTiledBuffer.bounds()).toRect();
818 layer->setModified(frameNumber,
true);
819 mTiledBuffer.
clear();
822void ScribbleArea::clearDrawingBuffer()
824 mTiledBuffer.
clear();
829 auto layer = mEditor->layers()->currentLayer();
831 if (!layer || !layer->isPaintable())
836 if (currentTool()->type() == ERASER) {
840 int frameNumber = mEditor->currentFrame();
841 if (layer->getKeyFrameAt(frameNumber)) {
return; }
844 int action = mPrefs->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION);
845 auto previousKeyFrame = layer->getLastKeyFrameAtPosition(frameNumber);
848 case KEEP_DRAWING_ON_PREVIOUS_KEY:
850 if (previousKeyFrame ==
nullptr) {
857 case DUPLICATE_PREVIOUS_KEY:
859 if (previousKeyFrame !=
nullptr) {
860 KeyFrame* dupKey = previousKeyFrame->clone();
862 mEditor->scrubTo(frameNumber);
873 drawCanvas(frameNumber, mCanvas.
rect());
882 int currentFrame = mEditor->currentFrame();
883 if (!currentTool()->isActive())
886 const int frameNumber = mEditor->layers()->lastFrameAtFrame(currentFrame);
890 drawCanvas(currentFrame, event->
rect());
894 auto cacheKeyIter = mPixmapCacheKeys.
find(
static_cast<unsigned>(frameNumber));
898 drawCanvas(currentFrame, event->
rect());
910 prepCanvas(currentFrame);
911 prepCameraPainter(currentFrame);
912 prepOverlays(currentFrame);
914 mCanvasPainter.paintCached(event->
rect());
915 mCameraPainter.paintCached(event->
rect());
918 if (currentTool()->type() == MOVE)
920 Layer* layer = mEditor->layers()->currentLayer();
922 if (layer->type() == Layer::VECTOR)
924 VectorImage* vectorImage = currentVectorImage(layer);
925 if (vectorImage !=
nullptr)
927 vectorImage->setModified(
true);
935 painter.setWorldMatrixEnabled(
false);
940 painter.setClipRect(event->
rect());
941 painter.drawPixmap(
QPointF(), mCanvas);
943 currentTool()->paint(painter, event->
rect());
945 if (!editor()->playback()->isPlaying())
947 Layer* layer = mEditor->layers()->currentLayer();
948 if (layer->type() == Layer::VECTOR)
950 VectorImage* vectorImage = currentVectorImage(layer);
951 if (vectorImage !=
nullptr)
953 switch (currentTool()->type())
958 auto selectMan = mEditor->select();
960 painter.setWorldMatrixEnabled(
false);
964 painter.setPen(pen2);
967 color =
QColor(200, 200, 200);
968 painter.setBrush(color);
970 for (
int k = 0; k < vectorSelection.curve.
size(); k++)
972 int curveNumber = vectorSelection.curve.
at(k);
974 for (
int vertexNumber = -1; vertexNumber < vectorImage->
getCurveSize(curveNumber); vertexNumber++)
977 QRectF rectangle(mEditor->view()->mapCanvasToScreen(vertexPoint) -
QPointF(3.0, 3.0),
QSizeF(7, 7));
978 if (
rect().contains(mEditor->view()->mapCanvasToScreen(vertexPoint).
toPoint()))
980 painter.drawRect(rectangle);
985 color =
QColor(100, 100, 255);
986 painter.setBrush(color);
987 for (
int k = 0; k < vectorSelection.vertex.
size(); k++)
989 VertexRef vertexRef = vectorSelection.vertex.
at(k);
992 painter.drawRect(rectangle0);
995 color =
QColor(255, 0, 0);
996 painter.setBrush(color);
998 if (vectorSelection.curve.
size() > 0)
1000 for (
int k = 0; k < closestVertices.
size(); k++)
1006 painter.drawRect(rectangle);
1020 mOverlayPainter.paint(painter,
rect());
1023 if (mEditor->select()->somethingSelected())
1025 paintSelectionVisuals(painter);
1031 painter.setWorldMatrixEnabled(
false);
1040void ScribbleArea::paintSelectionVisuals(
QPainter &painter)
1042 Object*
object = mEditor->object();
1044 auto selectMan = mEditor->select();
1046 QRectF currentSelectionRect = selectMan->mySelectionRect();
1048 if (currentSelectionRect.
isEmpty()) {
return; }
1050 TransformParameters params = { currentSelectionRect, editor()->view()->getView(), selectMan->selectionTransform() };
1051 mSelectionPainter.paint(painter,
object, mEditor->currentLayerIndex(), currentTool(), params);
1052 emit selectionUpdated();
1057 Q_ASSERT(layer->type() == Layer::BITMAP);
1058 auto bitmapLayer =
static_cast<LayerBitmap*
>(layer);
1059 return bitmapLayer->getLastBitmapImageAtFrame(mEditor->currentFrame());
1064 Q_ASSERT(layer->type() == Layer::VECTOR);
1065 auto vectorLayer =
static_cast<LayerVector*
>(layer);
1066 return vectorLayer->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
1069void ScribbleArea::prepCameraPainter(
int frame)
1071 Object*
object = mEditor->object();
1073 mCameraPainter.preparePainter(
object,
1074 mEditor->currentLayerIndex(),
1076 mEditor->view()->getView(),
1077 mEditor->playback()->isPlaying(),
1079 mPrefs->getFloat(SETTING::LAYER_VISIBILITY_THRESHOLD),
1080 mEditor->view()->getViewScaleInverse());
1083 onionSkinOptions.enabledWhilePlaying = mPrefs->getInt(SETTING::ONION_WHILE_PLAYBACK);
1084 onionSkinOptions.isPlaying = mEditor->playback()->isPlaying();
1085 onionSkinOptions.isAbsolute = (mPrefs->getString(SETTING::ONION_TYPE) ==
"absolute");
1086 onionSkinOptions.skinPrevFrames = mPrefs->isOn(SETTING::PREV_ONION);
1087 onionSkinOptions.skinNextFrames = mPrefs->isOn(SETTING::NEXT_ONION);
1088 onionSkinOptions.colorizePrevFrames = mPrefs->isOn(SETTING::ONION_RED);
1089 onionSkinOptions.colorizeNextFrames = mPrefs->isOn(SETTING::ONION_BLUE);
1090 onionSkinOptions.framesToSkinPrev = mPrefs->getInt(SETTING::ONION_PREV_FRAMES_NUM);
1091 onionSkinOptions.framesToSkinNext = mPrefs->getInt(SETTING::ONION_NEXT_FRAMES_NUM);
1092 onionSkinOptions.maxOpacity = mPrefs->getInt(SETTING::ONION_MAX_OPACITY);
1093 onionSkinOptions.minOpacity = mPrefs->getInt(SETTING::ONION_MIN_OPACITY);
1095 mCameraPainter.setOnionSkinPainterOptions(onionSkinOptions);
1098void ScribbleArea::prepCanvas(
int frame)
1100 Object*
object = mEditor->object();
1103 o.bOnionSkinMultiLayer = mPrefs->isOn(SETTING::ONION_MUTLIPLE_LAYERS);
1104 o.bAntiAlias = mPrefs->isOn(SETTING::ANTIALIAS);
1105 o.bThinLines = mPrefs->isOn(SETTING::INVISIBLE_LINES);
1106 o.bOutlines = mPrefs->isOn(SETTING::OUTLINES);
1107 o.eLayerVisibility = mLayerVisibility;
1108 o.fLayerVisibilityThreshold = mPrefs->getFloat(SETTING::LAYER_VISIBILITY_THRESHOLD);
1109 o.scaling = mEditor->view()->scaling();
1113 onionSkinOptions.enabledWhilePlaying = mPrefs->getInt(SETTING::ONION_WHILE_PLAYBACK);
1114 onionSkinOptions.isPlaying = mEditor->playback()->isPlaying();
1115 onionSkinOptions.isAbsolute = (mPrefs->getString(SETTING::ONION_TYPE) ==
"absolute");
1116 onionSkinOptions.skinPrevFrames = mPrefs->isOn(SETTING::PREV_ONION);
1117 onionSkinOptions.skinNextFrames = mPrefs->isOn(SETTING::NEXT_ONION);
1118 onionSkinOptions.colorizePrevFrames = mPrefs->isOn(SETTING::ONION_RED);
1119 onionSkinOptions.colorizeNextFrames = mPrefs->isOn(SETTING::ONION_BLUE);
1120 onionSkinOptions.framesToSkinPrev = mPrefs->getInt(SETTING::ONION_PREV_FRAMES_NUM);
1121 onionSkinOptions.framesToSkinNext = mPrefs->getInt(SETTING::ONION_NEXT_FRAMES_NUM);
1122 onionSkinOptions.maxOpacity = mPrefs->getInt(SETTING::ONION_MAX_OPACITY);
1123 onionSkinOptions.minOpacity = mPrefs->getInt(SETTING::ONION_MIN_OPACITY);
1125 mCanvasPainter.setOnionSkinOptions(onionSkinOptions);
1126 mCanvasPainter.setOptions(o);
1130 mCanvasPainter.setViewTransform(vm->getView(), vm->getViewInverse());
1131 mCanvasPainter.setTransformedSelection(sm->mySelectionRect().
toRect(), sm->selectionTransform());
1133 mCanvasPainter.setPaintSettings(
object, mEditor->layers()->currentLayerIndex(), frame, &mTiledBuffer);
1136void ScribbleArea::drawCanvas(
int frame,
QRect rect)
1139 prepCameraPainter(frame);
1140 prepOverlays(frame);
1141 mCanvasPainter.paint(
rect);
1142 mCameraPainter.paint(
rect);
1145void ScribbleArea::setGaussianGradient(
QGradient &gradient,
QColor color, qreal opacity, qreal offset)
1147 if (offset < 0) { offset = 0; }
1148 if (offset > 100) { offset = 100; }
1150 int r = color.
red();
1151 int g = color.
green();
1152 int b = color.
blue();
1153 qreal a = color.
alphaF();
1155 int mainColorAlpha = qRound(a * 255 * opacity);
1158 int alphaAdded = qRound((mainColorAlpha * offset) / 100);
1162 gradient.
setColorAt(1.0 - (offset / 100.0),
QColor(r, g, b, mainColorAlpha - alphaAdded));
1167 mTiledBuffer.
drawPath(mEditor->view()->mapScreenToCanvas(path), pen, brush, cm, mPrefs->isOn(SETTING::ANTIALIAS));
1170void ScribbleArea::drawPen(
QPointF thePoint, qreal brushWidth,
QColor fillColor,
bool useAA)
1176void ScribbleArea::drawPencil(
QPointF thePoint, qreal brushWidth, qreal fixedBrushFeather,
QColor fillColor, qreal opacity)
1187 setGaussianGradient(radialGrad, fillColor, opacity, mOffset);
1203 blitRect.extend(mEditor->view()->mapCanvasToScreen(mTiledBuffer.bounds()).toRect());
1205 QRect updateRect = mEditor->view()->mapCanvasToScreen(path.
boundingRect()).toRect();
1207 blitRect.extend(updateRect);
1209 mTiledBuffer.
clear();
1216void ScribbleArea::endStroke()
1218 if (mEditor->layers()->currentLayer()->type() == Layer::BITMAP) {
1219 paintBitmapBuffer();
1225void ScribbleArea::flipSelection(
bool flipVertical)
1230void ScribbleArea::prepOverlays(
int frame)
1234 o.bGrid = mPrefs->isOn(SETTING::GRID);
1235 o.nGridSizeW = mPrefs->getInt(SETTING::GRID_SIZE_W);
1236 o.nGridSizeH = mPrefs->getInt(SETTING::GRID_SIZE_H);
1237 o.bCenter = mPrefs->isOn(SETTING::OVERLAY_CENTER);
1238 o.bThirds = mPrefs->isOn(SETTING::OVERLAY_THIRDS);
1239 o.bGoldenRatio = mPrefs->isOn(SETTING::OVERLAY_GOLDEN);
1240 o.bSafeArea = mPrefs->isOn(SETTING::OVERLAY_SAFE);
1241 o.bPerspective1 = mPrefs->isOn(SETTING::OVERLAY_PERSPECTIVE1);
1242 o.bPerspective2 = mPrefs->isOn(SETTING::OVERLAY_PERSPECTIVE2);
1243 o.bPerspective3 = mPrefs->isOn(SETTING::OVERLAY_PERSPECTIVE3);
1244 o.nOverlayAngle = mPrefs->getInt(SETTING::OVERLAY_ANGLE);
1245 o.bActionSafe = mPrefs->isOn(SETTING::ACTION_SAFE_ON);
1246 o.nActionSafe = mPrefs->getInt(SETTING::ACTION_SAFE);
1247 o.bShowSafeAreaHelperText = mPrefs->isOn(SETTING::OVERLAY_SAFE_HELPER_TEXT_ON);
1248 o.bTitleSafe = mPrefs->isOn(SETTING::TITLE_SAFE_ON);
1249 o.nTitleSafe = mPrefs->getInt(SETTING::TITLE_SAFE);
1250 o.nOverlayAngle = mPrefs->getInt(SETTING::OVERLAY_ANGLE);
1251 o.bShowHandle = mEditor->tools()->currentTool()->type() == MOVE && mEditor->layers()->currentLayer()->type() != Layer::CAMERA;
1253 o.mSinglePerspPoint = mEditor->overlays()->getSinglePerspectivePoint();
1254 o.mLeftPerspPoint = mEditor->overlays()->getLeftPerspectivePoint();
1255 o.mRightPerspPoint = mEditor->overlays()->getRightPerspectivePoint();
1256 o.mMiddlePerspPoint = mEditor->overlays()->getMiddlePerspectivePoint();
1258 o.nFrameIndex = frame;
1260 mOverlayPainter.setOptions(o);
1261 mOverlayPainter.preparePainter(mEditor->layers()->getCameraLayerBelow(mEditor->currentLayerIndex()),
palette());
1264 mOverlayPainter.setViewTransform(vm->getView());
1267void ScribbleArea::blurBrush(
BitmapImage *bmiSource_,
QPointF srcPoint_,
QPointF thePoint_, qreal brushWidth_, qreal mOffset_, qreal opacity_)
1270 setGaussianGradient(radialGrad,
QColor(255, 255, 255, 127), opacity_, mOffset_);
1272 QRectF srcRect(srcPoint_.
x() - 0.5 * brushWidth_, srcPoint_.
y() - 0.5 * brushWidth_, brushWidth_, brushWidth_);
1273 QRectF trgRect(thePoint_.
x() - 0.5 * brushWidth_, thePoint_.
y() - 0.5 * brushWidth_, brushWidth_, brushWidth_);
1275 BitmapImage bmiSrcClip = bmiSource_->copy(srcRect.toAlignedRect());
1279 bmiSrcClip.bounds().
moveTo(trgRect.topLeft().toPoint());
1284void ScribbleArea::liquifyBrush(
BitmapImage *bmiSource_,
QPointF srcPoint_,
QPointF thePoint_, qreal brushWidth_, qreal mOffset_, qreal opacity_)
1286 QPointF delta = (thePoint_ - srcPoint_);
1287 QRectF trgRect(thePoint_.
x() - 0.5 * brushWidth_, thePoint_.
y() - 0.5 * brushWidth_, brushWidth_, brushWidth_);
1290 setGaussianGradient(radialGrad,
QColor(255, 255, 255, 255), opacity_, mOffset_);
1297 qreal factor, factorGrad;
1299 for (
int yb = bmiTmpClip.top(); yb < bmiTmpClip.bottom(); yb++)
1301 for (
int xb = bmiTmpClip.left(); xb < bmiTmpClip.right(); xb++)
1304 color.
setRgba(bmiTmpClip.pixel(xb, yb));
1305 factorGrad = color.
alphaF();
1307 int xa = xb - factorGrad * delta.
x();
1308 int ya = yb - factorGrad * delta.
y();
1310 color.
setRgba(bmiSource_->pixel(xa, ya));
1325 bmiTmpClip.setPixel(xb, yb, color.
rgba());
1329 bmiTmpClip.setPixel(xb, yb, qRgba(255, 255, 255, 0));
1339QPointF ScribbleArea::getCentralPoint()
1344void ScribbleArea::applyTransformedSelection()
1346 mCanvasPainter.ignoreTransformedSelection();
1348 Layer* layer = mEditor->layers()->currentLayer();
1349 if (layer ==
nullptr) {
return; }
1351 auto selectMan = mEditor->select();
1352 if (selectMan->somethingSelected())
1354 if (selectMan->mySelectionRect().isEmpty() || selectMan->selectionTransform().isIdentity()) {
return; }
1356 if (layer->type() == Layer::BITMAP)
1359 BitmapImage* bitmapImage = currentBitmapImage(layer);
1360 if (bitmapImage ==
nullptr) {
return; }
1361 BitmapImage transformedImage = bitmapImage->transformed(selectMan->mySelectionRect().toRect(), selectMan->selectionTransform(),
true);
1364 bitmapImage->clear(selectMan->mySelectionRect());
1367 else if (layer->type() == Layer::VECTOR)
1372 VectorImage* vectorImage = currentVectorImage(layer);
1373 if (vectorImage ==
nullptr) {
return; }
1378 mEditor->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
1384void ScribbleArea::cancelTransformedSelection()
1386 mCanvasPainter.ignoreTransformedSelection();
1388 auto selectMan = mEditor->select();
1389 if (selectMan->somethingSelected())
1391 Layer* layer = mEditor->layers()->currentLayer();
1392 if (layer ==
nullptr) {
return; }
1394 if (layer->type() == Layer::VECTOR)
1396 VectorImage* vectorImage = currentVectorImage(layer);
1397 if (vectorImage !=
nullptr)
1403 mEditor->select()->setSelection(selectMan->mySelectionRect(),
false);
1405 selectMan->resetSelectionProperties();
1408 mEditor->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
1413void ScribbleArea::toggleThinLines()
1415 bool previousValue = mPrefs->isOn(SETTING::INVISIBLE_LINES);
1416 setEffect(SETTING::INVISIBLE_LINES, !previousValue);
1419void ScribbleArea::setLayerVisibility(LayerVisibility visibility)
1421 mLayerVisibility = visibility;
1422 mPrefs->set(SETTING::LAYER_VISIBILITY,
static_cast<int>(mLayerVisibility));
1427void ScribbleArea::increaseLayerVisibilityIndex()
1430 mPrefs->set(SETTING::LAYER_VISIBILITY,
static_cast<int>(mLayerVisibility));
1435void ScribbleArea::decreaseLayerVisibilityIndex()
1438 mPrefs->set(SETTING::LAYER_VISIBILITY,
static_cast<int>(mLayerVisibility));
1446BaseTool* ScribbleArea::currentTool()
const
1448 return editor()->tools()->currentTool();
1451void ScribbleArea::deleteSelection()
1453 auto selectMan = mEditor->select();
1454 if (selectMan->somethingSelected())
1456 Layer* layer = mEditor->layers()->currentLayer();
1457 if (layer ==
nullptr) {
return; }
1461 mEditor->backup(
tr(
"Delete Selection",
"Undo Step: clear the selection area."));
1463 selectMan->clearCurves();
1464 if (layer->type() == Layer::VECTOR)
1466 VectorImage* vectorImage = currentVectorImage(layer);
1467 Q_CHECK_PTR(vectorImage);
1470 else if (layer->type() == Layer::BITMAP)
1472 BitmapImage* bitmapImage = currentBitmapImage(layer);
1473 Q_CHECK_PTR(bitmapImage);
1474 bitmapImage->clear(selectMan->mySelectionRect());
1476 mEditor->setModified(mEditor->currentLayerIndex(), mEditor->currentFrame());
1480void ScribbleArea::clearImage()
1482 Layer* layer = mEditor->layers()->currentLayer();
1483 if (layer ==
nullptr) {
return; }
1485 if (layer->type() == Layer::VECTOR)
1487 mEditor->backup(
tr(
"Clear Image",
"Undo step text"));
1489 VectorImage* vectorImage = currentVectorImage(layer);
1490 if (vectorImage !=
nullptr)
1492 vectorImage->
clear();
1494 mEditor->select()->clearCurves();
1495 mEditor->select()->clearVertices();
1497 else if (layer->type() == Layer::BITMAP)
1499 mEditor->backup(
tr(
"Clear Image",
"Undo step text"));
1501 BitmapImage* bitmapImage = currentBitmapImage(layer);
1502 if (bitmapImage ==
nullptr)
return;
1503 bitmapImage->clear();
1509 mEditor->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
1512void ScribbleArea::paletteColorChanged(
QColor color)
1516 for (
int i = 0; i < mEditor->layers()->count(); i++)
1518 Layer* layer = mEditor->layers()->getLayer(i);
1519 if (layer->type() == Layer::VECTOR)
1521 VectorImage* vectorImage =
static_cast<LayerVector*
>(layer)->getVectorImageAtFrame(mEditor->currentFrame());
1522 if (vectorImage !=
nullptr)
1524 vectorImage->modification();
KeyFrame * addNewKey()
Attempts to create a new keyframe at the current frame and layer.
void frameModified(int frameNumber)
This should be emitted after modifying the frame content.
QList< int > dirtyFrames() const
Returns a list of dirty frame positions.
virtual bool addKeyFrame(int position, KeyFrame *pKeyFrame)
Adds a keyframe at the given position, unless one already exists.
void clearDirtyFrames()
Clear the list of dirty keyframes.
Qt::MouseButton button() const
Returns Qt::MouseButton()
Qt::MouseButtons buttons() const
Returns Qt::MouseButtons()
void onScrubbed(int frameNumber)
Frame scrubbed, invalidate relevant cache.
void onToolPropertyUpdated(ToolType, ToolPropertyType)
Tool property updated, invalidate cache and frame if needed.
void onViewChanged()
View updated, invalidate relevant cache.
void onObjectLoaded()
Object updated, invalidate all cache.
void invalidateCacheForDirtyFrames()
invalidate cache for dirty keyframes.
void updateFrame()
Update frame.
void handleDrawingOnEmptyFrame()
Call this when starting to use a paint tool.
void invalidatePainterCaches()
Invalidate the layer pixmap and camera painter caches.
void invalidateOnionSkinsCacheAround(int frame)
invalidate onion skin cache around frame
void onSelectionChanged()
Selection was changed, keep cache.
void onOnionSkinTypeChanged()
Onion skin type changed, all frames will be affected.
void onFramesModified()
Multiple frames modified, invalidate cache for affected frames.
void onToolChanged(ToolType)
Tool changed, invalidate cache and frame if needed.
void onPlayStateChanged()
Playstate changed, invalidate relevant cache.
void invalidateAllCache()
Invalidate all cache.
void invalidateCacheForFrame(int frameNumber)
Invalidate cache for the given frame.
void onLayerChanged()
Layer changed, invalidate relevant cache.
void onFrameModified(int frameNumber)
Frame modified, invalidate cache for frame if any.
void flipSelection(bool flipVertical)
ScribbleArea::flipSelection flip selection along the X or Y axis.
void drawPath(QPainterPath path, QPen pen, QBrush brush, QPainter::CompositionMode cm, bool antialiasing)
Draws a path with the specified parameters to the tiled buffer.
void clear()
Clears the content of the tiled buffer.
void drawImage(const QImage &image, const QRect &imageBounds, QPainter::CompositionMode cm, bool antialiasing)
Draws a image with the specified parameters to the tiled buffer.
void drawBrush(QPointF point, qreal brushWidth, QPen pen, QBrush brush, QPainter::CompositionMode cm, bool antialiasing)
Draws a brush with the specified parameters to the tiled buffer.
QPointF getVertex(int curveNumber, int vertexNumber)
VectorImage::getVertex.
void clear()
VectorImage::clear.
void applySelectionTransformation()
VectorImage::applySelectionTransformation.
void setSelectionTransformation(QTransform transform)
VectorImage::setSelectionTransformation.
int getCurveSize(int curveNumber)
VectorImage::getCurveSize.
void deleteSelection()
VectorImage::deleteSelection.
qreal alphaF() const const
QEvent::Type type() const const
void setColorAt(qreal position, const QColor &color)
bool isAutoRepeat() const const
Qt::KeyboardModifiers modifiers() const const
qreal length() const const
const T & at(int i) const const
QMap::iterator find(const Key &key)
int remove(const Key &key)
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
const QPointF & localPos() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString tr(const char *sourceText, const char *disambiguation, int n)
qreal devicePixelRatioF() const const
QRectF boundingRect() const const
const QRect & rect() const const
void setDevicePixelRatio(qreal scaleFactor)
QPixmap * find(const QString &key)
bool insert(const QString &key, const QPixmap &pixmap)
void remove(const QString &key)
void setCacheLimit(int n)
bool isNull() const const
QPoint toPoint() const const
QRect adjusted(int dx1, int dy1, int dx2, int dy2) const const
void moveTo(int x, int y)
bool isEmpty() const const
QRect toAlignedRect() const const
QRect toRect() const const
const QPointF & posF() const const
void setInterval(int msec)
bool isActive() const const
const QPointF & posF() const const
QPointF position() const const