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 emit requestFocus(
this);
379 processed = currentTool()->enterEvent(
static_cast<QEnterEvent*
>(event)) || processed;
382 processed = currentTool()->leaveEvent(event) || processed;
392void ScribbleArea::keyPressEvent(
QKeyEvent *event)
397 if (isPointerInUse()) {
return; }
399 if (currentTool()->keyPressEvent(event))
406 editor()->tools()->setTemporaryTool(ERASER, {},
event->modifiers()))
413 auto selectMan = mEditor->select();
414 bool isSomethingSelected = selectMan->somethingSelected();
415 if (isSomethingSelected)
417 keyEventForSelection(event);
425void ScribbleArea::keyEventForSelection(
QKeyEvent* event)
427 auto selectMan = mEditor->select();
428 switch (event->
key())
431 selectMan->translate(
QPointF(1, 0));
432 selectMan->calculateSelectionTransformation();
436 selectMan->translate(
QPointF(-1, 0));
437 selectMan->calculateSelectionTransformation();
441 selectMan->translate(
QPointF(0, -1));
442 selectMan->calculateSelectionTransformation();
446 selectMan->translate(
QPointF(0, 1));
447 selectMan->calculateSelectionTransformation();
451 applyTransformedSelection();
452 mEditor->deselectAll();
455 cancelTransformedSelection();
456 mEditor->deselectAll();
460 mEditor->deselectAll();
474void ScribbleArea::keyEvent(
QKeyEvent* event)
476 switch (event->
key())
479 mEditor->scrubForward();
482 mEditor->scrubBackward();
485 mEditor->layers()->gotoNextLayer();
488 mEditor->layers()->gotoPreviouslayer();
502void ScribbleArea::keyReleaseEvent(
QKeyEvent *event)
510 if (event->
key() == 0)
516 editor()->tools()->tryClearTemporaryTool(
static_cast<Qt::Key>(event->
key()));
519 if (isPointerInUse()) {
return; }
521 if (currentTool()->keyReleaseEvent(event))
533 if (isPointerInUse())
return;
536 const QPoint pixels =
event->pixelDelta();
537 const QPoint angle =
event->angleDelta();
538#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
539 const QPointF offset = mEditor->view()->mapScreenToCanvas(event->
position());
541 const QPointF offset = mEditor->view()->mapScreenToCanvas(event->
posF());
544 const qreal currentScale = mEditor->view()->scaling();
548 if (!isX11 && !pixels.
isNull())
558 const qreal newScale = currentScale * std::pow(100, (delta * mDeltaFactor) / (12.0 * 120));
559 mEditor->view()->scaleAtOffset(newScale, offset);
568#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
569 if (event.pointerType() == QPointingDevice::PointerType::Eraser)
574 editor()->tools()->tabletSwitchToEraser();
578 editor()->tools()->tabletRestorePrevTool();
581 if (event.eventType() == PointerEvent::Press)
591 mIsFirstClick =
false;
592 mDoubleClickTimer->
start();
593 pointerPressEvent(&event);
598 mTabletPressPos = e->
posF();
600 if (mDoubleClickMillis <= DOUBLE_CLICK_THRESHOLD && distance < 5.0) {
601 currentTool()->pointerDoubleClickEvent(&event);
606 pointerPressEvent(&event);
609 mTabletInUse =
event.isAccepted();
611 else if (event.eventType() == PointerEvent::Move)
613 if (!mTabletHasEntered && !
hasFocus()) {
614 emit requestFocus(
this);
615 mTabletHasEntered =
true;
619 pointerMoveEvent(&event);
622 else if (event.eventType() == PointerEvent::Release)
624 mTabletReleaseMillisAgo = 0;
625 mMouseFilterTimer->
start();
628 pointerReleaseEvent(&event);
629 mTabletInUse =
false;
631 mTabletHasEntered =
false;
634#if defined Q_OS_LINUX
650void ScribbleArea::pointerPressEvent(
PointerEvent* event)
652 bool isCameraLayer = mEditor->layers()->currentLayer()->type() == Layer::CAMERA;
655 Layer* layer = mEditor->layers()->currentLayer();
656 if (!layer->visible())
667 editor()->tools()->setTemporaryTool(HAND, event->
buttons()))
669 currentTool()->pointerPressEvent(event);
672 currentTool()->pointerPressEvent(event);
678 currentTool()->pointerMoveEvent(event);
681void ScribbleArea::pointerReleaseEvent(
PointerEvent* event)
683 currentTool()->pointerReleaseEvent(event);
685 editor()->tools()->tryClearTemporaryTool(event->
button());
688void ScribbleArea::handleDoubleClick()
690 mDoubleClickMillis += 100;
692 if (mDoubleClickMillis >= DOUBLE_CLICK_THRESHOLD)
694 mDoubleClickMillis = 0;
695 mIsFirstClick =
true;
696 mDoubleClickTimer->
stop();
700void ScribbleArea::tabletReleaseEventFired()
708 mTabletReleaseMillisAgo += 50;
710 if (mTabletReleaseMillisAgo >= MOUSE_FILTER_THRESHOLD) {
711 mTabletReleaseMillisAgo = 0;
712 mMouseFilterTimer->
stop();
718 if (mTabletInUse || (mMouseFilterTimer->
isActive() && mTabletReleaseMillisAgo < MOUSE_FILTER_THRESHOLD))
725 pointerPressEvent(&event);
726 mMouseInUse =
event.isAccepted();
731 if (mTabletInUse || (mMouseFilterTimer->
isActive() && mTabletReleaseMillisAgo < MOUSE_FILTER_THRESHOLD)) { e->
ignore();
return; }
734 pointerMoveEvent(&event);
737void ScribbleArea::mouseReleaseEvent(
QMouseEvent* e)
739 if (mTabletInUse || (mMouseFilterTimer->
isActive() && mTabletReleaseMillisAgo < MOUSE_FILTER_THRESHOLD)) { e->
ignore();
return; }
742 pointerReleaseEvent(&event);
746void ScribbleArea::mouseDoubleClickEvent(
QMouseEvent* e)
748 if (mTabletInUse) { e->
ignore();
return; }
751 currentTool()->pointerDoubleClickEvent(&event);
760 mEditor->view()->setCanvasSize(
size());
764 mCanvasPainter.reset();
765 mCameraPainter.reset();
768void ScribbleArea::showLayerNotVisibleWarning()
771 tr(
"You are trying to modify a hidden layer! Please select another layer (or make the current layer visible)."),
776void ScribbleArea::paintBitmapBuffer()
780 Q_ASSERT(layer->type() == Layer::BITMAP);
782 int frameNumber = mEditor->currentFrame();
786 if (layer->getLastKeyFrameAtPosition(frameNumber) ==
nullptr)
792 BitmapImage* targetImage = currentBitmapImage(layer);
793 if (targetImage !=
nullptr)
796 switch (currentTool()->type())
808 targetImage->paste(&mTiledBuffer, cm);
811 QRect rect = mEditor->view()->mapCanvasToScreen(mTiledBuffer.bounds()).toRect();
815 layer->setModified(frameNumber,
true);
816 mTiledBuffer.
clear();
819void ScribbleArea::clearDrawingBuffer()
821 mTiledBuffer.
clear();
826 auto layer = mEditor->layers()->currentLayer();
828 if (!layer || !layer->isPaintable())
833 if (currentTool()->type() == ERASER) {
837 int frameNumber = mEditor->currentFrame();
838 if (layer->getKeyFrameAt(frameNumber)) {
return; }
841 int action = mPrefs->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION);
842 auto previousKeyFrame = layer->getLastKeyFrameAtPosition(frameNumber);
845 case KEEP_DRAWING_ON_PREVIOUS_KEY:
847 if (previousKeyFrame ==
nullptr) {
854 case DUPLICATE_PREVIOUS_KEY:
856 if (previousKeyFrame !=
nullptr) {
857 KeyFrame* dupKey = previousKeyFrame->clone();
859 mEditor->scrubTo(frameNumber);
870 drawCanvas(frameNumber, mCanvas.
rect());
880 int currentFrame = mEditor->currentFrame();
881 if (!currentTool()->isActive())
884 const int frameNumber = mEditor->layers()->lastFrameAtFrame(currentFrame);
888 drawCanvas(currentFrame, event->
rect());
892 auto cacheKeyIter = mPixmapCacheKeys.
find(
static_cast<unsigned>(frameNumber));
896 drawCanvas(currentFrame, event->
rect());
908 prepCanvas(currentFrame);
909 prepCameraPainter(currentFrame);
910 prepOverlays(currentFrame);
912 mCanvasPainter.paintCached(event->
rect());
913 mCameraPainter.paintCached(event->
rect());
916 if (currentTool()->type() == MOVE)
918 Layer* layer = mEditor->layers()->currentLayer();
920 if (layer->type() == Layer::VECTOR)
922 VectorImage* vectorImage = currentVectorImage(layer);
923 if (vectorImage !=
nullptr)
925 vectorImage->setModified(
true);
933 painter.setWorldMatrixEnabled(
false);
938 painter.setClipRect(event->
rect());
939 painter.drawPixmap(
QPointF(), mCanvas);
941 currentTool()->paint(painter, event->
rect());
943 if (!editor()->playback()->isPlaying())
945 Layer* layer = mEditor->layers()->currentLayer();
946 if (layer->type() == Layer::VECTOR)
948 VectorImage* vectorImage = currentVectorImage(layer);
949 if (vectorImage !=
nullptr)
951 switch (currentTool()->type())
956 auto selectMan = mEditor->select();
958 painter.setWorldMatrixEnabled(
false);
962 painter.setPen(pen2);
965 color =
QColor(200, 200, 200);
966 painter.setBrush(color);
968 for (
int k = 0; k < vectorSelection.curve.
size(); k++)
970 int curveNumber = vectorSelection.curve.
at(k);
972 for (
int vertexNumber = -1; vertexNumber < vectorImage->
getCurveSize(curveNumber); vertexNumber++)
975 QRectF rectangle(mEditor->view()->mapCanvasToScreen(vertexPoint) -
QPointF(3.0, 3.0),
QSizeF(7, 7));
976 if (
rect().contains(mEditor->view()->mapCanvasToScreen(vertexPoint).
toPoint()))
978 painter.drawRect(rectangle);
983 color =
QColor(100, 100, 255);
984 painter.setBrush(color);
985 for (
int k = 0; k < vectorSelection.vertex.
size(); k++)
987 VertexRef vertexRef = vectorSelection.vertex.
at(k);
990 painter.drawRect(rectangle0);
993 color =
QColor(255, 0, 0);
994 painter.setBrush(color);
996 if (vectorSelection.curve.
size() > 0)
998 for (
int k = 0; k < closestVertices.
size(); k++)
1004 painter.drawRect(rectangle);
1018 mOverlayPainter.paint(painter,
rect());
1021 if (mEditor->select()->somethingSelected())
1023 paintSelectionVisuals(painter);
1029 painter.setWorldMatrixEnabled(
false);
1038void ScribbleArea::paintSelectionVisuals(
QPainter &painter)
1040 Object*
object = mEditor->object();
1042 auto selectMan = mEditor->select();
1044 QRectF currentSelectionRect = selectMan->mySelectionRect();
1046 TransformParameters params = { currentSelectionRect, editor()->view()->getView(), selectMan->selectionTransform() };
1048 mSelectionPainter.paint(painter,
1050 mEditor->currentLayerIndex(),
1051 static_cast<const TransformTool*
>(editor()->tools()->getTool(SELECT))->transformSettings(),
1053 emit selectionUpdated();
1058 Q_ASSERT(layer->type() == Layer::BITMAP);
1059 auto bitmapLayer =
static_cast<LayerBitmap*
>(layer);
1060 return bitmapLayer->getLastBitmapImageAtFrame(mEditor->currentFrame());
1065 Q_ASSERT(layer->type() == Layer::VECTOR);
1066 auto vectorLayer =
static_cast<LayerVector*
>(layer);
1067 return vectorLayer->getLastVectorImageAtFrame(mEditor->currentFrame());
1070void ScribbleArea::prepCameraPainter(
int frame)
1072 Object*
object = mEditor->object();
1074 mCameraPainter.preparePainter(
object,
1075 mEditor->currentLayerIndex(),
1077 mEditor->view()->getView(),
1078 mEditor->playback()->isPlaying(),
1080 mPrefs->getFloat(SETTING::LAYER_VISIBILITY_THRESHOLD),
1084 onionSkinOptions.enabledWhilePlaying = mPrefs->getInt(SETTING::ONION_WHILE_PLAYBACK);
1085 onionSkinOptions.isPlaying = mEditor->playback()->isPlaying();
1086 onionSkinOptions.isAbsolute = (mPrefs->getString(SETTING::ONION_TYPE) ==
"absolute");
1087 onionSkinOptions.skinPrevFrames = mPrefs->isOn(SETTING::PREV_ONION);
1088 onionSkinOptions.skinNextFrames = mPrefs->isOn(SETTING::NEXT_ONION);
1089 onionSkinOptions.colorizePrevFrames = mPrefs->isOn(SETTING::ONION_RED);
1090 onionSkinOptions.colorizeNextFrames = mPrefs->isOn(SETTING::ONION_BLUE);
1091 onionSkinOptions.framesToSkinPrev = mPrefs->getInt(SETTING::ONION_PREV_FRAMES_NUM);
1092 onionSkinOptions.framesToSkinNext = mPrefs->getInt(SETTING::ONION_NEXT_FRAMES_NUM);
1093 onionSkinOptions.maxOpacity = mPrefs->getInt(SETTING::ONION_MAX_OPACITY);
1094 onionSkinOptions.minOpacity = mPrefs->getInt(SETTING::ONION_MIN_OPACITY);
1096 mCameraPainter.setOnionSkinPainterOptions(onionSkinOptions);
1099void ScribbleArea::prepCanvas(
int frame)
1101 Object*
object = mEditor->object();
1104 o.bOnionSkinMultiLayer = mPrefs->isOn(SETTING::ONION_MUTLIPLE_LAYERS);
1105 o.bAntiAlias = mPrefs->isOn(SETTING::ANTIALIAS);
1106 o.bThinLines = mPrefs->isOn(SETTING::INVISIBLE_LINES);
1107 o.bOutlines = mPrefs->isOn(SETTING::OUTLINES);
1108 o.eLayerVisibility = mLayerVisibility;
1109 o.fLayerVisibilityThreshold = mPrefs->getFloat(SETTING::LAYER_VISIBILITY_THRESHOLD);
1110 o.scaling = mEditor->view()->scaling();
1114 onionSkinOptions.enabledWhilePlaying = mPrefs->getInt(SETTING::ONION_WHILE_PLAYBACK);
1115 onionSkinOptions.isPlaying = mEditor->playback()->isPlaying();
1116 onionSkinOptions.isAbsolute = (mPrefs->getString(SETTING::ONION_TYPE) ==
"absolute");
1117 onionSkinOptions.skinPrevFrames = mPrefs->isOn(SETTING::PREV_ONION);
1118 onionSkinOptions.skinNextFrames = mPrefs->isOn(SETTING::NEXT_ONION);
1119 onionSkinOptions.colorizePrevFrames = mPrefs->isOn(SETTING::ONION_RED);
1120 onionSkinOptions.colorizeNextFrames = mPrefs->isOn(SETTING::ONION_BLUE);
1121 onionSkinOptions.framesToSkinPrev = mPrefs->getInt(SETTING::ONION_PREV_FRAMES_NUM);
1122 onionSkinOptions.framesToSkinNext = mPrefs->getInt(SETTING::ONION_NEXT_FRAMES_NUM);
1123 onionSkinOptions.maxOpacity = mPrefs->getInt(SETTING::ONION_MAX_OPACITY);
1124 onionSkinOptions.minOpacity = mPrefs->getInt(SETTING::ONION_MIN_OPACITY);
1126 mCanvasPainter.setOnionSkinOptions(onionSkinOptions);
1127 mCanvasPainter.setOptions(o);
1131 mCanvasPainter.setViewTransform(vm->getView(), vm->getViewInverse());
1132 mCanvasPainter.setTransformedSelection(sm->mySelectionRect().
toRect(), sm->selectionTransform());
1134 mCanvasPainter.setPaintSettings(
object, mEditor->layers()->currentLayerIndex(), frame, &mTiledBuffer);
1137void ScribbleArea::drawCanvas(
int frame,
QRect rect)
1140 prepCameraPainter(frame);
1141 prepOverlays(frame);
1142 mCanvasPainter.paint(
rect);
1143 mCameraPainter.paint(
rect);
1146void ScribbleArea::setGaussianGradient(
QGradient &gradient,
QColor color, qreal opacity, qreal offset)
1148 if (offset < 0) { offset = 0; }
1149 if (offset > 100) { offset = 100; }
1151 int r = color.
red();
1152 int g = color.
green();
1153 int b = color.
blue();
1154 qreal a = color.
alphaF();
1156 int mainColorAlpha = qRound(a * 255 * opacity);
1159 int alphaAdded = qRound((mainColorAlpha * offset) / 100);
1163 gradient.
setColorAt(1.0 - (offset / 100.0),
QColor(r, g, b, mainColorAlpha - alphaAdded));
1168 mTiledBuffer.
drawPath(mEditor->view()->mapScreenToCanvas(path), pen, brush, cm, mPrefs->isOn(SETTING::ANTIALIAS));
1171void ScribbleArea::drawPen(
QPointF thePoint, qreal brushWidth,
QColor fillColor,
bool useAA)
1177void ScribbleArea::drawPencil(
QPointF thePoint, qreal brushWidth, qreal fixedBrushFeather,
QColor fillColor, qreal opacity)
1188 setGaussianGradient(radialGrad, fillColor, opacity, mOffset);
1204 blitRect.extend(mEditor->view()->mapCanvasToScreen(mTiledBuffer.bounds()).toRect());
1206 QRect updateRect = mEditor->view()->mapCanvasToScreen(path.
boundingRect()).toRect();
1208 blitRect.extend(updateRect);
1210 mTiledBuffer.
clear();
1217void ScribbleArea::endStroke()
1219 if (mEditor->layers()->currentLayer()->type() == Layer::BITMAP) {
1220 paintBitmapBuffer();
1226void ScribbleArea::flipSelection(
bool flipVertical)
1231void ScribbleArea::prepOverlays(
int frame)
1235 o.bGrid = mPrefs->isOn(SETTING::GRID);
1236 o.nGridSizeW = mPrefs->getInt(SETTING::GRID_SIZE_W);
1237 o.nGridSizeH = mPrefs->getInt(SETTING::GRID_SIZE_H);
1238 o.bCenter = mPrefs->isOn(SETTING::OVERLAY_CENTER);
1239 o.bThirds = mPrefs->isOn(SETTING::OVERLAY_THIRDS);
1240 o.bGoldenRatio = mPrefs->isOn(SETTING::OVERLAY_GOLDEN);
1241 o.bSafeArea = mPrefs->isOn(SETTING::OVERLAY_SAFE);
1242 o.bPerspective1 = mPrefs->isOn(SETTING::OVERLAY_PERSPECTIVE1);
1243 o.bPerspective2 = mPrefs->isOn(SETTING::OVERLAY_PERSPECTIVE2);
1244 o.bPerspective3 = mPrefs->isOn(SETTING::OVERLAY_PERSPECTIVE3);
1245 o.nOverlayAngle = mPrefs->getInt(SETTING::OVERLAY_ANGLE);
1246 o.bActionSafe = mPrefs->isOn(SETTING::ACTION_SAFE_ON);
1247 o.nActionSafe = mPrefs->getInt(SETTING::ACTION_SAFE);
1248 o.bShowSafeAreaHelperText = mPrefs->isOn(SETTING::OVERLAY_SAFE_HELPER_TEXT_ON);
1249 o.bTitleSafe = mPrefs->isOn(SETTING::TITLE_SAFE_ON);
1250 o.nTitleSafe = mPrefs->getInt(SETTING::TITLE_SAFE);
1251 o.nOverlayAngle = mPrefs->getInt(SETTING::OVERLAY_ANGLE);
1252 o.bShowHandle = mEditor->tools()->currentTool()->type() == MOVE && mEditor->layers()->currentLayer()->type() != Layer::CAMERA;
1254 o.mSinglePerspPoint = mEditor->overlays()->getSinglePerspectivePoint();
1255 o.mLeftPerspPoint = mEditor->overlays()->getLeftPerspectivePoint();
1256 o.mRightPerspPoint = mEditor->overlays()->getRightPerspectivePoint();
1257 o.mMiddlePerspPoint = mEditor->overlays()->getMiddlePerspectivePoint();
1259 o.nFrameIndex = frame;
1261 mOverlayPainter.setOptions(o);
1262 mOverlayPainter.preparePainter(mEditor->layers()->getCameraLayerBelow(mEditor->currentLayerIndex()),
palette());
1265 mOverlayPainter.setViewTransform(vm->getView());
1268void ScribbleArea::blurBrush(
BitmapImage *bmiSource_,
QPointF srcPoint_,
QPointF thePoint_, qreal brushWidth_, qreal mOffset_, qreal opacity_)
1271 setGaussianGradient(radialGrad,
QColor(255, 255, 255, 127), opacity_, mOffset_);
1273 QRectF srcRect(srcPoint_.
x() - 0.5 * brushWidth_, srcPoint_.
y() - 0.5 * brushWidth_, brushWidth_, brushWidth_);
1274 QRectF trgRect(thePoint_.
x() - 0.5 * brushWidth_, thePoint_.
y() - 0.5 * brushWidth_, brushWidth_, brushWidth_);
1276 BitmapImage bmiSrcClip = bmiSource_->copy(srcRect.toAlignedRect());
1280 bmiSrcClip.bounds().
moveTo(trgRect.topLeft().toPoint());
1285void ScribbleArea::liquifyBrush(
BitmapImage *bmiSource_,
QPointF srcPoint_,
QPointF thePoint_, qreal brushWidth_, qreal mOffset_, qreal opacity_)
1287 QPointF delta = (thePoint_ - srcPoint_);
1288 QRectF trgRect(thePoint_.
x() - 0.5 * brushWidth_, thePoint_.
y() - 0.5 * brushWidth_, brushWidth_, brushWidth_);
1291 setGaussianGradient(radialGrad,
QColor(255, 255, 255, 255), opacity_, mOffset_);
1298 qreal factor, factorGrad;
1300 for (
int yb = bmiTmpClip.top(); yb < bmiTmpClip.bottom(); yb++)
1302 for (
int xb = bmiTmpClip.left(); xb < bmiTmpClip.right(); xb++)
1305 color.
setRgba(bmiTmpClip.pixel(xb, yb));
1306 factorGrad = color.
alphaF();
1308 int xa = xb - factorGrad * delta.
x();
1309 int ya = yb - factorGrad * delta.
y();
1311 color.
setRgba(bmiSource_->pixel(xa, ya));
1326 bmiTmpClip.setPixel(xb, yb, color.
rgba());
1330 bmiTmpClip.setPixel(xb, yb, qRgba(255, 255, 255, 0));
1340QPointF ScribbleArea::getCentralPoint()
1345void ScribbleArea::applyTransformedSelection()
1347 mCanvasPainter.ignoreTransformedSelection();
1349 Layer* layer = mEditor->layers()->currentLayer();
1351 bool useAA = mEditor->tools()->getTool(ToolType::MOVE)->toolProperties().getInfo(TransformToolProperties::ANTI_ALIASING_ENABLED).boolValue();
1353 if (layer ==
nullptr) {
return; }
1355 auto selectMan = mEditor->select();
1356 if (selectMan->somethingSelected())
1358 if (selectMan->mySelectionRect().isEmpty() || selectMan->selectionTransform().isIdentity()) {
return; }
1360 if (layer->type() == Layer::BITMAP)
1363 BitmapImage* bitmapImage = currentBitmapImage(layer);
1364 if (bitmapImage ==
nullptr) {
return; }
1365 BitmapImage transformedImage = bitmapImage->transformed(selectMan->mySelectionRect().toRect(), selectMan->selectionTransform(), useAA);
1368 bitmapImage->clear(selectMan->mySelectionRect());
1371 else if (layer->type() == Layer::VECTOR)
1376 VectorImage* vectorImage = currentVectorImage(layer);
1377 if (vectorImage ==
nullptr) {
return; }
1382 mEditor->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
1388void ScribbleArea::cancelTransformedSelection()
1390 mCanvasPainter.ignoreTransformedSelection();
1392 auto selectMan = mEditor->select();
1393 if (selectMan->somethingSelected())
1395 Layer* layer = mEditor->layers()->currentLayer();
1396 if (layer ==
nullptr) {
return; }
1398 if (layer->type() == Layer::VECTOR)
1400 VectorImage* vectorImage = currentVectorImage(layer);
1401 if (vectorImage !=
nullptr)
1407 mEditor->select()->
setSelection(selectMan->mySelectionRect(),
false);
1409 selectMan->resetSelectionProperties();
1412 mEditor->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
1417void ScribbleArea::toggleThinLines()
1419 bool previousValue = mPrefs->isOn(SETTING::INVISIBLE_LINES);
1420 setEffect(SETTING::INVISIBLE_LINES, !previousValue);
1423void ScribbleArea::setLayerVisibility(LayerVisibility visibility)
1425 mLayerVisibility = visibility;
1426 mPrefs->set(SETTING::LAYER_VISIBILITY,
static_cast<int>(mLayerVisibility));
1431void ScribbleArea::increaseLayerVisibilityIndex()
1434 mPrefs->set(SETTING::LAYER_VISIBILITY,
static_cast<int>(mLayerVisibility));
1439void ScribbleArea::decreaseLayerVisibilityIndex()
1442 mPrefs->set(SETTING::LAYER_VISIBILITY,
static_cast<int>(mLayerVisibility));
1450BaseTool* ScribbleArea::currentTool()
const
1452 return editor()->tools()->currentTool();
1455void ScribbleArea::deleteSelection()
1457 auto selectMan = mEditor->select();
1458 if (selectMan->somethingSelected())
1460 Layer* layer = mEditor->layers()->currentLayer();
1461 if (layer ==
nullptr) {
return; }
1465 mEditor->backup(
tr(
"Delete Selection",
"Undo Step: clear the selection area."));
1467 selectMan->clearCurves();
1468 if (layer->type() == Layer::VECTOR)
1470 VectorImage* vectorImage = currentVectorImage(layer);
1471 Q_CHECK_PTR(vectorImage);
1474 else if (layer->type() == Layer::BITMAP)
1476 BitmapImage* bitmapImage = currentBitmapImage(layer);
1477 Q_CHECK_PTR(bitmapImage);
1478 bitmapImage->clear(selectMan->mySelectionRect());
1480 mEditor->setModified(mEditor->currentLayerIndex(), mEditor->currentFrame());
1484void ScribbleArea::clearImage()
1486 Layer* layer = mEditor->layers()->currentLayer();
1487 if (layer ==
nullptr) {
return; }
1489 if (layer->type() == Layer::VECTOR)
1491 mEditor->backup(
tr(
"Clear Image",
"Undo step text"));
1493 VectorImage* vectorImage = currentVectorImage(layer);
1494 if (vectorImage !=
nullptr)
1496 vectorImage->
clear();
1498 mEditor->select()->clearCurves();
1499 mEditor->select()->clearVertices();
1501 else if (layer->type() == Layer::BITMAP)
1503 mEditor->backup(
tr(
"Clear Image",
"Undo step text"));
1505 BitmapImage* bitmapImage = currentBitmapImage(layer);
1506 if (bitmapImage ==
nullptr)
return;
1507 bitmapImage->clear();
1513 mEditor->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
1516void ScribbleArea::paletteColorChanged(
QColor color)
1520 for (
int i = 0; i < mEditor->layers()->count(); i++)
1522 Layer* layer = mEditor->layers()->getLayer(i);
1523 if (layer->type() == Layer::VECTOR)
1525 VectorImage* vectorImage =
static_cast<LayerVector*
>(layer)->getVectorImageAtFrame(mEditor->currentFrame());
1526 if (vectorImage !=
nullptr)
1528 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