18#include "scribblearea.h"
21#include <QGuiApplication>
23#include <QPixmapCache>
27#include "transformtool.h"
28#include "pointerevent.h"
29#include "beziercurve.h"
32#include "layerbitmap.h"
33#include "layervector.h"
34#include "layercamera.h"
35#include "bitmapimage.h"
36#include "vectorimage.h"
40#include "onionskinpainteroptions.h"
42#include "colormanager.h"
43#include "toolmanager.h"
44#include "layermanager.h"
45#include "playbackmanager.h"
46#include "viewmanager.h"
47#include "selectionmanager.h"
48#include "overlaymanager.h"
51 mCanvasPainter(mCanvas),
52 mCameraPainter(mCanvas)
54 setObjectName(
"ScribbleArea");
61ScribbleArea::~ScribbleArea()
65bool ScribbleArea::init()
67 mPrefs = mEditor->preference();
68 mDoubleClickTimer =
new QTimer(
this);
69 mMouseFilterTimer =
new QTimer(
this);
71 connect(mPrefs, &PreferenceManager::optionChanged,
this, &ScribbleArea::settingUpdated);
78 connect(mEditor->select(), &SelectionManager::needDeleteSelection,
this, &ScribbleArea::deleteSelection);
80 connect(&mTiledBuffer, &TiledBuffer::tileUpdated,
this, &ScribbleArea::onTileUpdated);
81 connect(&mTiledBuffer, &TiledBuffer::tileCreated,
this, &ScribbleArea::onTileCreated);
86 const int curveSmoothingLevel = mPrefs->getInt(SETTING::CURVE_SMOOTHING);
87 mCurveSmoothingLevel = curveSmoothingLevel / 20.0;
89 mMakeInvisible =
false;
91 mLayerVisibility =
static_cast<LayerVisibility
>(mPrefs->getInt(SETTING::LAYER_VISIBILITY));
93 mDeltaFactor = mEditor->preference()->isOn(SETTING::INVERT_SCROLL_ZOOM_DIRECTION) ? -1 : 1;
96#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
103 mPixmapCacheKeys.
clear();
108void ScribbleArea::settingUpdated(SETTING setting)
112 case SETTING::CURVE_SMOOTHING:
113 setCurveSmoothing(mPrefs->getInt(SETTING::CURVE_SMOOTHING));
115 case SETTING::TOOL_CURSOR:
118 case SETTING::ONION_PREV_FRAMES_NUM:
119 case SETTING::ONION_NEXT_FRAMES_NUM:
120 case SETTING::ONION_MIN_OPACITY:
121 case SETTING::ONION_MAX_OPACITY:
124 case SETTING::ANTIALIAS:
126 case SETTING::GRID_SIZE_W:
127 case SETTING::GRID_SIZE_H:
128 case SETTING::OVERLAY_CENTER:
129 case SETTING::OVERLAY_THIRDS:
130 case SETTING::OVERLAY_GOLDEN:
131 case SETTING::OVERLAY_SAFE:
132 case SETTING::OVERLAY_PERSPECTIVE1:
133 case SETTING::OVERLAY_PERSPECTIVE2:
134 case SETTING::OVERLAY_PERSPECTIVE3:
135 case SETTING::ACTION_SAFE_ON:
136 case SETTING::ACTION_SAFE:
137 case SETTING::TITLE_SAFE_ON:
138 case SETTING::TITLE_SAFE:
139 case SETTING::OVERLAY_SAFE_HELPER_TEXT_ON:
140 case SETTING::PREV_ONION:
141 case SETTING::NEXT_ONION:
142 case SETTING::ONION_BLUE:
143 case SETTING::ONION_RED:
144 case SETTING::INVISIBLE_LINES:
145 case SETTING::OUTLINES:
146 case SETTING::ONION_TYPE:
147 case SETTING::ONION_WHILE_PLAYBACK:
150 case SETTING::ONION_MUTLIPLE_LAYERS:
153 case SETTING::LAYER_VISIBILITY_THRESHOLD:
154 case SETTING::LAYER_VISIBILITY:
155 setLayerVisibility(
static_cast<LayerVisibility
>(mPrefs->getInt(SETTING::LAYER_VISIBILITY)));
157 case SETTING::INVERT_SCROLL_ZOOM_DIRECTION:
158 mDeltaFactor = mEditor->preference()->isOn(SETTING::INVERT_SCROLL_ZOOM_DIRECTION) ? -1 : 1;
166void ScribbleArea::updateToolCursor()
171void ScribbleArea::setCurveSmoothing(
int newSmoothingLevel)
173 mCurveSmoothingLevel = newSmoothingLevel / 20.0;
177void ScribbleArea::setEffect(SETTING e,
bool isOn)
179 mPrefs->set(e, isOn);
188 Q_UNUSED(tiledBuffer);
195 Q_UNUSED(tiledBuffer)
202 if (currentTool()->isActive() && currentTool()->isDrawingTool()) {
211 Layer* currentLayer = mEditor->layers()->currentLayer();
222 if (frameNumber < 0) {
return; }
224 bool isOnionAbsolute = mPrefs->getString(SETTING::ONION_TYPE) ==
"absolute";
225 Layer *layer = mEditor->layers()->currentLayer(0);
230 if (mPrefs->isOn(SETTING::PREV_ONION))
232 int onionFrameNumber = frameNumber;
235 onionFrameNumber = layer->getPreviousFrameNumber(onionFrameNumber + 1,
true);
238 for(
int i = 1; i <= mPrefs->getInt(SETTING::ONION_PREV_FRAMES_NUM); i++)
240 onionFrameNumber = layer->getPreviousFrameNumber(onionFrameNumber, isOnionAbsolute);
241 if (onionFrameNumber < 0)
break;
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->getNextFrameNumber(onionFrameNumber, isOnionAbsolute);
254 if (onionFrameNumber < 0)
break;
263 if (currentTool()->isDrawingTool() && currentTool()->isActive()) {
return; }
266 mPixmapCacheKeys.
clear();
275 auto cacheKeyIter = mPixmapCacheKeys.
find(
static_cast<unsigned int>(frameNumber));
276 if (cacheKeyIter != mPixmapCacheKeys.
end())
279 unsigned int key = cacheKeyIter.key();
280 mPixmapCacheKeys.
remove(key);
286 mCameraPainter.resetCache();
287 mCanvasPainter.resetLayerCache();
293 int frame = mEditor->currentFrame();
295 prepCameraPainter(frame);
303 int currentFrame = mEditor->currentFrame();
304 if (mPrefs->isOn(SETTING::PREV_ONION) ||
305 mPrefs->isOn(SETTING::NEXT_ONION)) {
309 prepOverlays(currentFrame);
310 prepCameraPainter(currentFrame);
317 Q_UNUSED(frameNumber)
325 if (mPrefs->isOn(SETTING::PREV_ONION) || mPrefs->isOn(SETTING::NEXT_ONION)) {
333 if (mPrefs->isOn(SETTING::PREV_ONION) || mPrefs->isOn(SETTING::NEXT_ONION)) {
353 int currentFrame = mEditor->currentFrame();
368bool ScribbleArea::event(
QEvent *event)
370 bool processed =
false;
373 editor()->tools()->clearTemporaryTool();
377 processed = currentTool()->enterEvent(
static_cast<QEnterEvent*
>(event)) || processed;
380 processed = currentTool()->leaveEvent(event) || processed;
390void ScribbleArea::keyPressEvent(
QKeyEvent *event)
395 if (isPointerInUse()) {
return; }
397 if (currentTool()->keyPressEvent(event))
404 editor()->tools()->setTemporaryTool(ERASER, {},
event->modifiers()))
411 auto selectMan = mEditor->select();
412 bool isSomethingSelected = selectMan->somethingSelected();
413 if (isSomethingSelected)
415 keyEventForSelection(event);
423void ScribbleArea::keyEventForSelection(
QKeyEvent* event)
425 auto selectMan = mEditor->select();
426 switch (event->
key())
429 selectMan->translate(
QPointF(1, 0));
430 selectMan->calculateSelectionTransformation();
434 selectMan->translate(
QPointF(-1, 0));
435 selectMan->calculateSelectionTransformation();
439 selectMan->translate(
QPointF(0, -1));
440 selectMan->calculateSelectionTransformation();
444 selectMan->translate(
QPointF(0, 1));
445 selectMan->calculateSelectionTransformation();
449 applyTransformedSelection();
450 mEditor->deselectAll();
453 cancelTransformedSelection();
454 mEditor->deselectAll();
458 mEditor->deselectAll();
472void ScribbleArea::keyEvent(
QKeyEvent* event)
474 switch (event->
key())
477 mEditor->scrubForward();
480 mEditor->scrubBackward();
483 mEditor->layers()->gotoNextLayer();
486 mEditor->layers()->gotoPreviouslayer();
500void ScribbleArea::keyReleaseEvent(
QKeyEvent *event)
508 if (event->
key() == 0)
514 editor()->tools()->tryClearTemporaryTool(
static_cast<Qt::Key>(event->
key()));
517 if (isPointerInUse()) {
return; }
519 if (currentTool()->keyReleaseEvent(event))
531 if (isPointerInUse())
return;
534 const QPoint pixels =
event->pixelDelta();
535 const QPoint angle =
event->angleDelta();
536#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
537 const QPointF offset = mEditor->view()->mapScreenToCanvas(event->
position());
539 const QPointF offset = mEditor->view()->mapScreenToCanvas(event->
posF());
542 const qreal currentScale = mEditor->view()->scaling();
546 if (!isX11 && !pixels.
isNull())
556 const qreal newScale = currentScale * std::pow(100, (delta * mDeltaFactor) / (12.0 * 120));
557 mEditor->view()->scaleAtOffset(newScale, offset);
566#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
567 if (event.pointerType() == QPointingDevice::PointerType::Eraser)
572 editor()->tools()->tabletSwitchToEraser();
576 editor()->tools()->tabletRestorePrevTool();
579 if (event.eventType() == PointerEvent::Press)
584 mIsFirstClick =
false;
585 mDoubleClickTimer->
start();
586 pointerPressEvent(&event);
591 mTabletPressPos = e->
posF();
593 if (mDoubleClickMillis <= DOUBLE_CLICK_THRESHOLD && distance < 5.0) {
594 currentTool()->pointerDoubleClickEvent(&event);
599 pointerPressEvent(&event);
602 mTabletInUse =
event.isAccepted();
604 else if (event.eventType() == PointerEvent::Move)
608 pointerMoveEvent(&event);
611 else if (event.eventType() == PointerEvent::Release)
613 mTabletReleaseMillisAgo = 0;
614 mMouseFilterTimer->
start();
617 pointerReleaseEvent(&event);
618 mTabletInUse =
false;
622#if defined Q_OS_LINUX
638void ScribbleArea::pointerPressEvent(
PointerEvent* event)
640 bool isCameraLayer = mEditor->layers()->currentLayer()->type() == Layer::CAMERA;
643 Layer* layer = mEditor->layers()->currentLayer();
644 if (!layer->visible())
655 editor()->tools()->setTemporaryTool(HAND, event->
buttons()))
657 currentTool()->pointerPressEvent(event);
660 currentTool()->pointerPressEvent(event);
666 currentTool()->pointerMoveEvent(event);
669void ScribbleArea::pointerReleaseEvent(
PointerEvent* event)
671 currentTool()->pointerReleaseEvent(event);
673 editor()->tools()->tryClearTemporaryTool(event->
button());
676void ScribbleArea::handleDoubleClick()
678 mDoubleClickMillis += 100;
680 if (mDoubleClickMillis >= DOUBLE_CLICK_THRESHOLD)
682 mDoubleClickMillis = 0;
683 mIsFirstClick =
true;
684 mDoubleClickTimer->
stop();
688void ScribbleArea::tabletReleaseEventFired()
696 mTabletReleaseMillisAgo += 50;
698 if (mTabletReleaseMillisAgo >= MOUSE_FILTER_THRESHOLD) {
699 mTabletReleaseMillisAgo = 0;
700 mMouseFilterTimer->
stop();
706 if (mTabletInUse || (mMouseFilterTimer->
isActive() && mTabletReleaseMillisAgo < MOUSE_FILTER_THRESHOLD))
713 pointerPressEvent(&event);
714 mMouseInUse =
event.isAccepted();
719 if (mTabletInUse || (mMouseFilterTimer->
isActive() && mTabletReleaseMillisAgo < MOUSE_FILTER_THRESHOLD)) { e->
ignore();
return; }
722 pointerMoveEvent(&event);
725void ScribbleArea::mouseReleaseEvent(
QMouseEvent* e)
727 if (mTabletInUse || (mMouseFilterTimer->
isActive() && mTabletReleaseMillisAgo < MOUSE_FILTER_THRESHOLD)) { e->
ignore();
return; }
730 pointerReleaseEvent(&event);
734void ScribbleArea::mouseDoubleClickEvent(
QMouseEvent* e)
736 if (mTabletInUse) { e->
ignore();
return; }
739 currentTool()->pointerDoubleClickEvent(&event);
748 mEditor->view()->setCanvasSize(
size());
752 mCanvasPainter.reset();
753 mCameraPainter.reset();
756void ScribbleArea::showLayerNotVisibleWarning()
759 tr(
"You are trying to modify a hidden layer! Please select another layer (or make the current layer visible)."),
764void ScribbleArea::paintBitmapBuffer()
768 Q_ASSERT(layer->type() == Layer::BITMAP);
770 int frameNumber = mEditor->currentFrame();
774 if (layer->getLastKeyFrameAtPosition(frameNumber) ==
nullptr)
780 BitmapImage* targetImage = currentBitmapImage(layer);
781 if (targetImage !=
nullptr)
784 switch (currentTool()->type())
796 targetImage->paste(&mTiledBuffer, cm);
799 QRect rect = mEditor->view()->mapCanvasToScreen(mTiledBuffer.bounds()).toRect();
803 layer->setModified(frameNumber,
true);
804 mTiledBuffer.
clear();
807void ScribbleArea::clearDrawingBuffer()
809 mTiledBuffer.
clear();
814 auto layer = mEditor->layers()->currentLayer();
816 if (!layer || !layer->isPaintable())
821 if (currentTool()->type() == ERASER) {
825 int frameNumber = mEditor->currentFrame();
826 if (layer->getKeyFrameAt(frameNumber)) {
return; }
829 int action = mPrefs->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION);
830 auto previousKeyFrame = layer->getLastKeyFrameAtPosition(frameNumber);
833 case KEEP_DRAWING_ON_PREVIOUS_KEY:
835 if (previousKeyFrame ==
nullptr) {
842 case DUPLICATE_PREVIOUS_KEY:
844 if (previousKeyFrame !=
nullptr) {
845 KeyFrame* dupKey = previousKeyFrame->clone();
847 mEditor->scrubTo(frameNumber);
858 drawCanvas(frameNumber, mCanvas.
rect());
868 int currentFrame = mEditor->currentFrame();
869 if (!currentTool()->isActive())
872 const int frameNumber = mEditor->layers()->lastFrameAtFrame(currentFrame);
876 drawCanvas(currentFrame, event->
rect());
880 auto cacheKeyIter = mPixmapCacheKeys.
find(
static_cast<unsigned>(frameNumber));
884 drawCanvas(currentFrame, event->
rect());
896 prepCanvas(currentFrame);
897 prepCameraPainter(currentFrame);
898 prepOverlays(currentFrame);
900 mCanvasPainter.paintCached(event->
rect());
901 mCameraPainter.paintCached(event->
rect());
904 if (currentTool()->type() == MOVE)
906 Layer* layer = mEditor->layers()->currentLayer();
908 if (layer->type() == Layer::VECTOR)
910 VectorImage* vectorImage = currentVectorImage(layer);
911 if (vectorImage !=
nullptr)
913 vectorImage->setModified(
true);
921 painter.setWorldMatrixEnabled(
false);
926 painter.setClipRect(event->
rect());
927 painter.drawPixmap(
QPointF(), mCanvas);
929 currentTool()->paint(painter, event->
rect());
931 if (!editor()->playback()->isPlaying())
933 Layer* layer = mEditor->layers()->currentLayer();
934 if (layer->type() == Layer::VECTOR)
936 VectorImage* vectorImage = currentVectorImage(layer);
937 if (vectorImage !=
nullptr)
939 switch (currentTool()->type())
944 auto selectMan = mEditor->select();
946 painter.setWorldMatrixEnabled(
false);
950 painter.setPen(pen2);
953 color =
QColor(200, 200, 200);
954 painter.setBrush(color);
956 for (
int k = 0; k < vectorSelection.curve.
size(); k++)
958 int curveNumber = vectorSelection.curve.
at(k);
960 for (
int vertexNumber = -1; vertexNumber < vectorImage->
getCurveSize(curveNumber); vertexNumber++)
963 QRectF rectangle(mEditor->view()->mapCanvasToScreen(vertexPoint) -
QPointF(3.0, 3.0),
QSizeF(7, 7));
964 if (
rect().contains(mEditor->view()->mapCanvasToScreen(vertexPoint).
toPoint()))
966 painter.drawRect(rectangle);
971 color =
QColor(100, 100, 255);
972 painter.setBrush(color);
973 for (
int k = 0; k < vectorSelection.vertex.
size(); k++)
975 VertexRef vertexRef = vectorSelection.vertex.
at(k);
978 painter.drawRect(rectangle0);
981 color =
QColor(255, 0, 0);
982 painter.setBrush(color);
984 if (vectorSelection.curve.
size() > 0)
986 for (
int k = 0; k < closestVertices.
size(); k++)
992 painter.drawRect(rectangle);
1006 mOverlayPainter.paint(painter,
rect());
1009 if (mEditor->select()->somethingSelected())
1011 paintSelectionVisuals(painter);
1017 painter.setWorldMatrixEnabled(
false);
1026void ScribbleArea::paintSelectionVisuals(
QPainter &painter)
1028 Object*
object = mEditor->object();
1030 auto selectMan = mEditor->select();
1032 QRectF currentSelectionRect = selectMan->mySelectionRect();
1034 TransformParameters params = { currentSelectionRect, editor()->view()->getView(), selectMan->selectionTransform() };
1036 mSelectionPainter.paint(painter,
1038 mEditor->currentLayerIndex(),
1039 static_cast<const TransformTool*
>(editor()->tools()->getTool(SELECT))->transformSettings(),
1041 emit selectionUpdated();
1046 Q_ASSERT(layer->type() == Layer::BITMAP);
1047 auto bitmapLayer =
static_cast<LayerBitmap*
>(layer);
1048 return bitmapLayer->getLastBitmapImageAtFrame(mEditor->currentFrame());
1053 Q_ASSERT(layer->type() == Layer::VECTOR);
1054 auto vectorLayer =
static_cast<LayerVector*
>(layer);
1055 return vectorLayer->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
1058void ScribbleArea::prepCameraPainter(
int frame)
1060 Object*
object = mEditor->object();
1062 mCameraPainter.preparePainter(
object,
1063 mEditor->currentLayerIndex(),
1065 mEditor->view()->getView(),
1066 mEditor->playback()->isPlaying(),
1068 mPrefs->getFloat(SETTING::LAYER_VISIBILITY_THRESHOLD),
1072 onionSkinOptions.enabledWhilePlaying = mPrefs->getInt(SETTING::ONION_WHILE_PLAYBACK);
1073 onionSkinOptions.isPlaying = mEditor->playback()->isPlaying();
1074 onionSkinOptions.isAbsolute = (mPrefs->getString(SETTING::ONION_TYPE) ==
"absolute");
1075 onionSkinOptions.skinPrevFrames = mPrefs->isOn(SETTING::PREV_ONION);
1076 onionSkinOptions.skinNextFrames = mPrefs->isOn(SETTING::NEXT_ONION);
1077 onionSkinOptions.colorizePrevFrames = mPrefs->isOn(SETTING::ONION_RED);
1078 onionSkinOptions.colorizeNextFrames = mPrefs->isOn(SETTING::ONION_BLUE);
1079 onionSkinOptions.framesToSkinPrev = mPrefs->getInt(SETTING::ONION_PREV_FRAMES_NUM);
1080 onionSkinOptions.framesToSkinNext = mPrefs->getInt(SETTING::ONION_NEXT_FRAMES_NUM);
1081 onionSkinOptions.maxOpacity = mPrefs->getInt(SETTING::ONION_MAX_OPACITY);
1082 onionSkinOptions.minOpacity = mPrefs->getInt(SETTING::ONION_MIN_OPACITY);
1084 mCameraPainter.setOnionSkinPainterOptions(onionSkinOptions);
1087void ScribbleArea::prepCanvas(
int frame)
1089 Object*
object = mEditor->object();
1092 o.bOnionSkinMultiLayer = mPrefs->isOn(SETTING::ONION_MUTLIPLE_LAYERS);
1093 o.bAntiAlias = mPrefs->isOn(SETTING::ANTIALIAS);
1094 o.bThinLines = mPrefs->isOn(SETTING::INVISIBLE_LINES);
1095 o.bOutlines = mPrefs->isOn(SETTING::OUTLINES);
1096 o.eLayerVisibility = mLayerVisibility;
1097 o.fLayerVisibilityThreshold = mPrefs->getFloat(SETTING::LAYER_VISIBILITY_THRESHOLD);
1098 o.scaling = mEditor->view()->scaling();
1102 onionSkinOptions.enabledWhilePlaying = mPrefs->getInt(SETTING::ONION_WHILE_PLAYBACK);
1103 onionSkinOptions.isPlaying = mEditor->playback()->isPlaying();
1104 onionSkinOptions.isAbsolute = (mPrefs->getString(SETTING::ONION_TYPE) ==
"absolute");
1105 onionSkinOptions.skinPrevFrames = mPrefs->isOn(SETTING::PREV_ONION);
1106 onionSkinOptions.skinNextFrames = mPrefs->isOn(SETTING::NEXT_ONION);
1107 onionSkinOptions.colorizePrevFrames = mPrefs->isOn(SETTING::ONION_RED);
1108 onionSkinOptions.colorizeNextFrames = mPrefs->isOn(SETTING::ONION_BLUE);
1109 onionSkinOptions.framesToSkinPrev = mPrefs->getInt(SETTING::ONION_PREV_FRAMES_NUM);
1110 onionSkinOptions.framesToSkinNext = mPrefs->getInt(SETTING::ONION_NEXT_FRAMES_NUM);
1111 onionSkinOptions.maxOpacity = mPrefs->getInt(SETTING::ONION_MAX_OPACITY);
1112 onionSkinOptions.minOpacity = mPrefs->getInt(SETTING::ONION_MIN_OPACITY);
1114 mCanvasPainter.setOnionSkinOptions(onionSkinOptions);
1115 mCanvasPainter.setOptions(o);
1119 mCanvasPainter.setViewTransform(vm->getView(), vm->getViewInverse());
1120 mCanvasPainter.setTransformedSelection(sm->mySelectionRect().
toRect(), sm->selectionTransform());
1122 mCanvasPainter.setPaintSettings(
object, mEditor->layers()->currentLayerIndex(), frame, &mTiledBuffer);
1125void ScribbleArea::drawCanvas(
int frame,
QRect rect)
1128 prepCameraPainter(frame);
1129 prepOverlays(frame);
1130 mCanvasPainter.paint(
rect);
1131 mCameraPainter.paint(
rect);
1134void ScribbleArea::setGaussianGradient(
QGradient &gradient,
QColor color, qreal opacity, qreal offset)
1136 if (offset < 0) { offset = 0; }
1137 if (offset > 100) { offset = 100; }
1139 int r = color.
red();
1140 int g = color.
green();
1141 int b = color.
blue();
1142 qreal a = color.
alphaF();
1144 int mainColorAlpha = qRound(a * 255 * opacity);
1147 int alphaAdded = qRound((mainColorAlpha * offset) / 100);
1151 gradient.
setColorAt(1.0 - (offset / 100.0),
QColor(r, g, b, mainColorAlpha - alphaAdded));
1156 mTiledBuffer.
drawPath(mEditor->view()->mapScreenToCanvas(path), pen, brush, cm, mPrefs->isOn(SETTING::ANTIALIAS));
1159void ScribbleArea::drawPen(
QPointF thePoint, qreal brushWidth,
QColor fillColor,
bool useAA)
1165void ScribbleArea::drawPencil(
QPointF thePoint, qreal brushWidth, qreal fixedBrushFeather,
QColor fillColor, qreal opacity)
1176 setGaussianGradient(radialGrad, fillColor, opacity, mOffset);
1192 blitRect.extend(mEditor->view()->mapCanvasToScreen(mTiledBuffer.bounds()).toRect());
1194 QRect updateRect = mEditor->view()->mapCanvasToScreen(path.
boundingRect()).toRect();
1196 blitRect.extend(updateRect);
1198 mTiledBuffer.
clear();
1205void ScribbleArea::endStroke()
1207 if (mEditor->layers()->currentLayer()->type() == Layer::BITMAP) {
1208 paintBitmapBuffer();
1214void ScribbleArea::flipSelection(
bool flipVertical)
1219void ScribbleArea::prepOverlays(
int frame)
1223 o.bGrid = mPrefs->isOn(SETTING::GRID);
1224 o.nGridSizeW = mPrefs->getInt(SETTING::GRID_SIZE_W);
1225 o.nGridSizeH = mPrefs->getInt(SETTING::GRID_SIZE_H);
1226 o.bCenter = mPrefs->isOn(SETTING::OVERLAY_CENTER);
1227 o.bThirds = mPrefs->isOn(SETTING::OVERLAY_THIRDS);
1228 o.bGoldenRatio = mPrefs->isOn(SETTING::OVERLAY_GOLDEN);
1229 o.bSafeArea = mPrefs->isOn(SETTING::OVERLAY_SAFE);
1230 o.bPerspective1 = mPrefs->isOn(SETTING::OVERLAY_PERSPECTIVE1);
1231 o.bPerspective2 = mPrefs->isOn(SETTING::OVERLAY_PERSPECTIVE2);
1232 o.bPerspective3 = mPrefs->isOn(SETTING::OVERLAY_PERSPECTIVE3);
1233 o.nOverlayAngle = mPrefs->getInt(SETTING::OVERLAY_ANGLE);
1234 o.bActionSafe = mPrefs->isOn(SETTING::ACTION_SAFE_ON);
1235 o.nActionSafe = mPrefs->getInt(SETTING::ACTION_SAFE);
1236 o.bShowSafeAreaHelperText = mPrefs->isOn(SETTING::OVERLAY_SAFE_HELPER_TEXT_ON);
1237 o.bTitleSafe = mPrefs->isOn(SETTING::TITLE_SAFE_ON);
1238 o.nTitleSafe = mPrefs->getInt(SETTING::TITLE_SAFE);
1239 o.nOverlayAngle = mPrefs->getInt(SETTING::OVERLAY_ANGLE);
1240 o.bShowHandle = mEditor->tools()->currentTool()->type() == MOVE && mEditor->layers()->currentLayer()->type() != Layer::CAMERA;
1242 o.mSinglePerspPoint = mEditor->overlays()->getSinglePerspectivePoint();
1243 o.mLeftPerspPoint = mEditor->overlays()->getLeftPerspectivePoint();
1244 o.mRightPerspPoint = mEditor->overlays()->getRightPerspectivePoint();
1245 o.mMiddlePerspPoint = mEditor->overlays()->getMiddlePerspectivePoint();
1247 o.nFrameIndex = frame;
1249 mOverlayPainter.setOptions(o);
1250 mOverlayPainter.preparePainter(mEditor->layers()->getCameraLayerBelow(mEditor->currentLayerIndex()),
palette());
1253 mOverlayPainter.setViewTransform(vm->getView());
1256void ScribbleArea::blurBrush(
BitmapImage *bmiSource_,
QPointF srcPoint_,
QPointF thePoint_, qreal brushWidth_, qreal mOffset_, qreal opacity_)
1259 setGaussianGradient(radialGrad,
QColor(255, 255, 255, 127), opacity_, mOffset_);
1261 QRectF srcRect(srcPoint_.
x() - 0.5 * brushWidth_, srcPoint_.
y() - 0.5 * brushWidth_, brushWidth_, brushWidth_);
1262 QRectF trgRect(thePoint_.
x() - 0.5 * brushWidth_, thePoint_.
y() - 0.5 * brushWidth_, brushWidth_, brushWidth_);
1264 BitmapImage bmiSrcClip = bmiSource_->copy(srcRect.toAlignedRect());
1268 bmiSrcClip.bounds().
moveTo(trgRect.topLeft().toPoint());
1273void ScribbleArea::liquifyBrush(
BitmapImage *bmiSource_,
QPointF srcPoint_,
QPointF thePoint_, qreal brushWidth_, qreal mOffset_, qreal opacity_)
1275 QPointF delta = (thePoint_ - srcPoint_);
1276 QRectF trgRect(thePoint_.
x() - 0.5 * brushWidth_, thePoint_.
y() - 0.5 * brushWidth_, brushWidth_, brushWidth_);
1279 setGaussianGradient(radialGrad,
QColor(255, 255, 255, 255), opacity_, mOffset_);
1286 qreal factor, factorGrad;
1288 for (
int yb = bmiTmpClip.top(); yb < bmiTmpClip.bottom(); yb++)
1290 for (
int xb = bmiTmpClip.left(); xb < bmiTmpClip.right(); xb++)
1293 color.
setRgba(bmiTmpClip.pixel(xb, yb));
1294 factorGrad = color.
alphaF();
1296 int xa = xb - factorGrad * delta.
x();
1297 int ya = yb - factorGrad * delta.
y();
1299 color.
setRgba(bmiSource_->pixel(xa, ya));
1314 bmiTmpClip.setPixel(xb, yb, color.
rgba());
1318 bmiTmpClip.setPixel(xb, yb, qRgba(255, 255, 255, 0));
1328QPointF ScribbleArea::getCentralPoint()
1333void ScribbleArea::applyTransformedSelection()
1335 mCanvasPainter.ignoreTransformedSelection();
1337 Layer* layer = mEditor->layers()->currentLayer();
1339 bool useAA = mEditor->tools()->getTool(ToolType::MOVE)->toolProperties().getInfo(TransformToolProperties::ANTI_ALIASING_ENABLED).boolValue();
1341 if (layer ==
nullptr) {
return; }
1343 auto selectMan = mEditor->select();
1344 if (selectMan->somethingSelected())
1346 if (selectMan->mySelectionRect().isEmpty() || selectMan->selectionTransform().isIdentity()) {
return; }
1348 if (layer->type() == Layer::BITMAP)
1351 BitmapImage* bitmapImage = currentBitmapImage(layer);
1352 if (bitmapImage ==
nullptr) {
return; }
1353 BitmapImage transformedImage = bitmapImage->transformed(selectMan->mySelectionRect().toRect(), selectMan->selectionTransform(), useAA);
1356 bitmapImage->clear(selectMan->mySelectionRect());
1359 else if (layer->type() == Layer::VECTOR)
1364 VectorImage* vectorImage = currentVectorImage(layer);
1365 if (vectorImage ==
nullptr) {
return; }
1370 mEditor->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
1376void ScribbleArea::cancelTransformedSelection()
1378 mCanvasPainter.ignoreTransformedSelection();
1380 auto selectMan = mEditor->select();
1381 if (selectMan->somethingSelected())
1383 Layer* layer = mEditor->layers()->currentLayer();
1384 if (layer ==
nullptr) {
return; }
1386 if (layer->type() == Layer::VECTOR)
1388 VectorImage* vectorImage = currentVectorImage(layer);
1389 if (vectorImage !=
nullptr)
1395 mEditor->select()->
setSelection(selectMan->mySelectionRect(),
false);
1397 selectMan->resetSelectionProperties();
1400 mEditor->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
1405void ScribbleArea::toggleThinLines()
1407 bool previousValue = mPrefs->isOn(SETTING::INVISIBLE_LINES);
1408 setEffect(SETTING::INVISIBLE_LINES, !previousValue);
1411void ScribbleArea::setLayerVisibility(LayerVisibility visibility)
1413 mLayerVisibility = visibility;
1414 mPrefs->set(SETTING::LAYER_VISIBILITY,
static_cast<int>(mLayerVisibility));
1419void ScribbleArea::increaseLayerVisibilityIndex()
1422 mPrefs->set(SETTING::LAYER_VISIBILITY,
static_cast<int>(mLayerVisibility));
1427void ScribbleArea::decreaseLayerVisibilityIndex()
1430 mPrefs->set(SETTING::LAYER_VISIBILITY,
static_cast<int>(mLayerVisibility));
1438BaseTool* ScribbleArea::currentTool()
const
1440 return editor()->tools()->currentTool();
1443void ScribbleArea::deleteSelection()
1445 auto selectMan = mEditor->select();
1446 if (selectMan->somethingSelected())
1448 Layer* layer = mEditor->layers()->currentLayer();
1449 if (layer ==
nullptr) {
return; }
1453 mEditor->backup(
tr(
"Delete Selection",
"Undo Step: clear the selection area."));
1455 selectMan->clearCurves();
1456 if (layer->type() == Layer::VECTOR)
1458 VectorImage* vectorImage = currentVectorImage(layer);
1459 Q_CHECK_PTR(vectorImage);
1462 else if (layer->type() == Layer::BITMAP)
1464 BitmapImage* bitmapImage = currentBitmapImage(layer);
1465 Q_CHECK_PTR(bitmapImage);
1466 bitmapImage->clear(selectMan->mySelectionRect());
1468 mEditor->setModified(mEditor->currentLayerIndex(), mEditor->currentFrame());
1472void ScribbleArea::clearImage()
1474 Layer* layer = mEditor->layers()->currentLayer();
1475 if (layer ==
nullptr) {
return; }
1477 if (layer->type() == Layer::VECTOR)
1479 mEditor->backup(
tr(
"Clear Image",
"Undo step text"));
1481 VectorImage* vectorImage = currentVectorImage(layer);
1482 if (vectorImage !=
nullptr)
1484 vectorImage->
clear();
1486 mEditor->select()->clearCurves();
1487 mEditor->select()->clearVertices();
1489 else if (layer->type() == Layer::BITMAP)
1491 mEditor->backup(
tr(
"Clear Image",
"Undo step text"));
1493 BitmapImage* bitmapImage = currentBitmapImage(layer);
1494 if (bitmapImage ==
nullptr)
return;
1495 bitmapImage->clear();
1501 mEditor->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
1504void ScribbleArea::paletteColorChanged(
QColor color)
1508 for (
int i = 0; i < mEditor->layers()->count(); i++)
1510 Layer* layer = mEditor->layers()->getLayer(i);
1511 if (layer->type() == Layer::VECTOR)
1513 VectorImage* vectorImage =
static_cast<LayerVector*
>(layer)->getVectorImageAtFrame(mEditor->currentFrame());
1514 if (vectorImage !=
nullptr)
1516 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 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.
The SelectionManager class acts as the "Brain" of the selection system.
void flipSelection(bool flipVertical)
ScribbleArea::flipSelection flip selection along the X or Y axis.
void setSelection(QRectF rect, bool roundPixels=false)
Defines the selection area.
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 getScaleInversed() const
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)
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