diff --git a/core_lib/src/camerapainter.cpp b/core_lib/src/camerapainter.cpp index 580290f558..aa266381a2 100644 --- a/core_lib/src/camerapainter.cpp +++ b/core_lib/src/camerapainter.cpp @@ -56,8 +56,14 @@ void CameraPainter::preparePainter(const Object* object, mRelativeLayerOpacityThreshold = relativeLayerOpacityThreshold; mViewScale = viewScale; - mHandleColor = Qt::gray; + mHandleColor = Qt::white; + mHandleDisabledColor = Qt::black; mHandleTextColor = QColor(0, 0, 0); + + mHandlePen = QPen(); + mHandlePen.setColor(QColor(0, 0, 0, 255)); + mHandlePen.setWidth(2); + } void CameraPainter::paint() const @@ -109,42 +115,56 @@ void CameraPainter::paintVisuals(QPainter& painter) const if (cameraLayerBelow == nullptr) { return; } - int startLayerI = 0; - int endLayerI = mObject->getLayerCount() - 1; - for (int i = startLayerI; i <= endLayerI; i++) { - Layer* layer = mObject->getLayer(i); - if (layer->type() != Layer::CAMERA) { continue; } + const Layer* currentLayer = mObject->getLayer(mCurrentLayerIndex); - LayerCamera* cameraLayer = static_cast(layer); + if (mLayerVisibility == LayerVisibility::CURRENTONLY && currentLayer->type() != Layer::CAMERA) { return; } - bool isCurrentLayer = cameraLayer == cameraLayerBelow; + if (!mIsPlaying || mOnionSkinOptions.enabledWhilePlaying) { - if (!cameraLayer->visible() || (mLayerVisibility == LayerVisibility::CURRENTONLY && !isCurrentLayer)) { continue; } + int startLayerI = 0; + int endLayerI = mObject->getLayerCount() - 1; + for (int i = startLayerI; i <= endLayerI; i++) { + Layer* layer = mObject->getLayer(i); + if (layer->type() != Layer::CAMERA) { continue; } - painter.save(); - painter.setOpacity(1); - if (mLayerVisibility == LayerVisibility::RELATED && !isCurrentLayer) { - painter.setOpacity(calculateRelativeOpacityForLayer(mCurrentLayerIndex, i, mRelativeLayerOpacityThreshold)); - } + LayerCamera* cameraLayer = static_cast(layer); - paintInterpolations(painter, cameraLayer); + bool isCurrentLayer = cameraLayer == cameraLayerBelow; - painter.restore(); - } + painter.save(); + painter.setOpacity(1); + if (mLayerVisibility == LayerVisibility::RELATED && !isCurrentLayer) { + painter.setOpacity(calculateRelativeOpacityForLayer(mCurrentLayerIndex, i, mRelativeLayerOpacityThreshold)); + } - if (!mIsPlaying) { - QTransform camTransform = cameraLayerBelow->getViewAtFrame(mFrameIndex); - QRect cameraRect = cameraLayerBelow->getViewRect(); - if (mShowHandles) { - int frame = cameraLayerBelow->getPreviousKeyFramePosition(mFrameIndex); - Camera* cam = cameraLayerBelow->getLastCameraAtFrame(qMax(frame, mFrameIndex), 0); - Q_ASSERT(cam); - qreal scale = cam->scaling(); - qreal rotation = cam->rotation(); - QPointF translation = cam->translation(); - paintHandles(painter, camTransform, cameraRect, translation, scale, rotation, !cameraLayerBelow->keyExists(mFrameIndex)); + paintOnionSkinning(painter, cameraLayer); + + painter.restore(); } - paintBorder(painter, camTransform, cameraRect); + } + + if (!cameraLayerBelow->visible()) { return; } + + QTransform camTransform = cameraLayerBelow->getViewAtFrame(mFrameIndex); + QRect cameraRect = cameraLayerBelow->getViewRect(); + paintBorder(painter, camTransform, cameraRect); + + // Show handles while we're on a camera layer and not doing playback + if (!mIsPlaying && mShowHandles) { + int frame = cameraLayerBelow->getPreviousKeyFramePosition(mFrameIndex); + Camera* cam = cameraLayerBelow->getLastCameraAtFrame(qMax(frame, mFrameIndex), 0); + Q_ASSERT(cam); + qreal scale = cam->scaling(); + qreal rotation = cam->rotation(); + QPointF translation = cam->translation(); + paintHandles(painter, camTransform, cameraRect, translation, scale, rotation, !cameraLayerBelow->keyExists(mFrameIndex)); + } + + if (mShowHandles) { + const LayerCamera* layerCamera = static_cast(currentLayer); + currentLayer->foreachKeyFrame([&] (KeyFrame* keyframe) { + paintInterpolations(painter, layerCamera, keyframe); + }); } } @@ -176,9 +196,6 @@ void CameraPainter::paintHandles(QPainter& painter, const QTransform& camTransfo { painter.save(); - painter.setBrush(Qt::NoBrush); - painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - // if the current view is narrower than the camera field // Indicates that the quality of the output will be degraded if (scale > 1) @@ -193,9 +210,6 @@ void CameraPainter::paintHandles(QPainter& painter, const QTransform& camTransfo QPolygonF camPolygon = mViewTransform.map(camTransform.inverted().map(QPolygon(cameraRect))); painter.drawPolygon(camPolygon); - - painter.setPen(QColor(0, 0, 0, 100)); - QTransform scaleT; scaleT.scale(1, 1); scaleT.rotate(rotation); @@ -205,10 +219,11 @@ void CameraPainter::paintHandles(QPainter& painter, const QTransform& camTransfo painter.drawPolygon(nonScaledCamPoly); painter.drawText(nonScaledCamPoly[0]-QPoint(0, 2), "100%"); - painter.setPen(mHandleTextColor); if (hollowHandles) { - painter.setBrush(Qt::transparent); + painter.setPen(mHandleDisabledColor); + painter.setBrush(Qt::gray); } else { + painter.setPen(mHandlePen); painter.setBrush(mHandleColor); } int handleW = HANDLE_WIDTH; @@ -242,11 +257,6 @@ void CameraPainter::paintHandles(QPainter& painter, const QTransform& camTransfo painter.drawLine(topCenter, QPoint(rotationHandle.x(), (rotationHandle.y()))); - // Make sure the line is not painted inside the circle, while hollow - if (hollowHandles) { - painter.setCompositionMode(QPainter::CompositionMode_SourceOut); - } - painter.drawEllipse(QRectF((rotationHandle.x() - handleW*0.5), (rotationHandle.y() - handleW*0.5), handleW, handleW)); @@ -254,95 +264,95 @@ void CameraPainter::paintHandles(QPainter& painter, const QTransform& camTransfo painter.restore(); } -void CameraPainter::paintInterpolations(QPainter& painter, const LayerCamera* cameraLayer) const +void CameraPainter::paintInterpolations(QPainter& painter, const LayerCamera* cameraLayer, const KeyFrame* keyframe) const { - if (mIsPlaying && !mOnionSkinOptions.enabledWhilePlaying) { return; } - QColor cameraDotColor = cameraLayer->getDotColor(); + int frame = keyframe->pos(); + int nextFrame = cameraLayer->getNextKeyFramePosition(frame); - QPolygon cameraViewPoly = cameraLayer->getViewRect(); - QPen onionSkinPen; + if (cameraLayer->getShowCameraPath() && !cameraLayer->hasSameTranslation(frame, nextFrame)) { + painter.save(); - cameraLayer->foreachKeyFrame([&] (KeyFrame* keyframe) { - int frame = keyframe->pos(); - int nextFrame = cameraLayer->getNextKeyFramePosition(frame); + QPointF cameraPathPoint = mViewTransform.map(cameraLayer->getPathControlPointAtFrame(mFrameIndex)); + painter.setBrush(cameraDotColor); + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - if (cameraLayer->getShowCameraPath() && !cameraLayer->hasSameTranslation(frame, nextFrame)) { - painter.save(); + // Highlight current dot + QPen pen(Qt::black); + pen.setWidth(2); + painter.setPen(pen); + cameraPathPoint = mViewTransform.map(cameraLayer->getViewAtFrame(mFrameIndex).inverted().map(QRectF(cameraLayer->getViewRect()).center())); + painter.drawEllipse(cameraPathPoint, DOT_WIDTH/2., DOT_WIDTH/2.); - QPointF cameraPathPoint = mViewTransform.map(cameraLayer->getPathControlPointAtFrame(mFrameIndex)); - painter.setBrush(cameraDotColor); - painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - painter.setRenderHint(QPainter::Antialiasing); + cameraPathPoint = mViewTransform.map(cameraLayer->getPathControlPointAtFrame(frame + 1)); - // Highlight current dot - QPen pen(Qt::black); - pen.setWidth(2); - painter.setPen(pen); - cameraPathPoint = mViewTransform.map(cameraLayer->getViewAtFrame(mFrameIndex).inverted().map(QRectF(cameraLayer->getViewRect()).center())); - painter.drawEllipse(cameraPathPoint, DOT_WIDTH/2., DOT_WIDTH/2.); + painter.save(); + QColor color = cameraDotColor; + if (mFrameIndex > frame && mFrameIndex < nextFrame) + color.setAlphaF(0.5); + else + color.setAlphaF(0.2); + painter.setPen(Qt::black); + painter.setBrush(color); - cameraPathPoint = mViewTransform.map(cameraLayer->getPathControlPointAtFrame(frame + 1)); + for (int frameInBetween = frame; frameInBetween <= nextFrame ; frameInBetween++) + { + QTransform transform = cameraLayer->getViewAtFrame(frameInBetween); + QPointF center = mViewTransform.map(transform.inverted().map(QRectF(cameraLayer->getViewRect()).center())); + painter.drawEllipse(center, DOT_WIDTH/2., DOT_WIDTH/2.); + } + painter.restore(); - int distance = nextFrame - frame; - // It makes no sense to paint the path when there's no interpolation. - if (distance >= 2) { - paintPath(painter, cameraLayer, frame, cameraPathPoint, cameraLayer->keyExists(mFrameIndex)); - } + int distance = nextFrame - frame; + // It makes no sense to paint the path when there's no interpolation. + if (distance >= 2 && !mIsPlaying) { + paintControlPoint(painter, cameraLayer, frame, cameraPathPoint, cameraLayer->keyExists(mFrameIndex)); + } - QColor color = cameraDotColor; - if (mFrameIndex > frame && mFrameIndex < nextFrame) - color.setAlphaF(0.5); - else - color.setAlphaF(0.2); - painter.setPen(Qt::black); - painter.setBrush(color); + painter.restore(); + } +} + +void CameraPainter::paintOnionSkinning(QPainter& painter, const LayerCamera* cameraLayer) const +{ + QPolygon cameraViewPoly = cameraLayer->getViewRect(); + QPen onionSkinPen; - for (int frameInBetween = frame; frameInBetween <= nextFrame ; frameInBetween++) - { - QTransform transform = cameraLayer->getViewAtFrame(frameInBetween); - QPointF center = mViewTransform.map(transform.inverted().map(QRectF(cameraLayer->getViewRect()).center())); - painter.drawEllipse(center, DOT_WIDTH/2., DOT_WIDTH/2.); + painter.save(); + painter.setBrush(Qt::NoBrush); + + onionSkinPen.setStyle(Qt::PenStyle::DashLine); + mOnionSkinPainter.paint(painter, cameraLayer, mOnionSkinOptions, mFrameIndex, [&] (OnionSkinPaintState state, int onionSkinNumber) { + + QPolygon cameraPoly = mViewTransform.map(cameraLayer->getViewAtFrame(onionSkinNumber).inverted().map(cameraViewPoly)); + if (state == OnionSkinPaintState::PREV) { + + if (mOnionSkinOptions.colorizePrevFrames) { + onionSkinPen.setColor(Qt::red); + } + + painter.setPen(onionSkinPen); + painter.drawPolygon(cameraPoly); + } else if (state == OnionSkinPaintState::NEXT) { + if (mOnionSkinOptions.colorizeNextFrames) { + onionSkinPen.setColor(Qt::blue); } + painter.setPen(onionSkinPen); + painter.drawPolygon(cameraPoly); + } else if (state == OnionSkinPaintState::CURRENT) { + painter.save(); + painter.setPen(Qt::black); + painter.drawPolygon(cameraPoly); painter.restore(); } - - painter.save(); - painter.setBrush(Qt::NoBrush); - - onionSkinPen.setStyle(Qt::PenStyle::DashLine); - mOnionSkinPainter.paint(painter, cameraLayer, mOnionSkinOptions, mFrameIndex, [&] (OnionSkinPaintState state, int onionSkinNumber) { - - QPolygon cameraPoly = mViewTransform.map(cameraLayer->getViewAtFrame(onionSkinNumber).inverted().map(cameraViewPoly)); - if (state == OnionSkinPaintState::PREV) { - - if (mOnionSkinOptions.colorizePrevFrames) { - onionSkinPen.setColor(Qt::red); - } - - painter.setPen(onionSkinPen); - painter.drawPolygon(cameraPoly); - } else if (state == OnionSkinPaintState::NEXT) { - if (mOnionSkinOptions.colorizeNextFrames) { - onionSkinPen.setColor(Qt::blue); - } - - painter.setPen(onionSkinPen); - painter.drawPolygon(cameraPoly); - } else if (state == OnionSkinPaintState::CURRENT) { - painter.save(); - painter.setPen(Qt::black); - painter.drawPolygon(cameraPoly); - painter.restore(); - } - }); - painter.restore(); }); + painter.restore(); } -void CameraPainter::paintPath(QPainter& painter, const LayerCamera* cameraLayer, const int frameIndex, const QPointF& pathPoint, bool hollowHandle) const +void CameraPainter::paintControlPoint(QPainter& painter, const LayerCamera* cameraLayer, const int frameIndex, const QPointF& pathPoint, bool hollowHandle) const { + painter.save(); // if active path, draw bezier help lines for active path QList points = cameraLayer->getBezierPointsAtFrame(frameIndex + 1); @@ -355,36 +365,34 @@ void CameraPainter::paintPath(QPainter& painter, const LayerCamera* cameraLayer, QPointF p2 = mViewTransform.map(points.at(2)); painter.save(); - QPen pen (mHandleColor, 0.5, Qt::PenStyle::DashLine); + QPen pen (Qt::black, 0.5, Qt::PenStyle::DashLine); painter.setPen(pen); painter.drawLine(p0, p1); painter.drawLine(p1, p2); painter.restore(); } - if (mShowHandles) { - painter.save(); - // draw movemode in text - painter.setPen(Qt::black); - QString pathType = cameraLayer->getInterpolationTextAtFrame(frameIndex); + // draw movemode in text + painter.setPen(Qt::black); + QString pathType = cameraLayer->getInterpolationTextAtFrame(frameIndex); - // Space text according to path point so it doesn't overlap - painter.drawText(pathPoint - QPoint(0, HANDLE_WIDTH), pathType); - painter.restore(); + // Space text according to path point so it doesn't overlap + painter.drawText(pathPoint - QPoint(0, HANDLE_WIDTH), pathType); + painter.restore(); - // if active path, draw move handle - painter.save(); - painter.setRenderHint(QPainter::Antialiasing, false); - painter.setPen(mHandleTextColor); + // if active path, draw move handle + painter.save(); + painter.setPen(mHandleTextColor); - if (hollowHandle) { - painter.setBrush(Qt::NoBrush); - } else { - painter.setBrush(mHandleColor); - } - painter.drawRect(static_cast(pathPoint.x() - HANDLE_WIDTH/2), - static_cast(pathPoint.y() - HANDLE_WIDTH/2), - HANDLE_WIDTH, HANDLE_WIDTH); - painter.restore(); + if (hollowHandle) { + painter.setPen(mHandleDisabledColor); + painter.setBrush(Qt::gray); + } else { + painter.setPen(mHandlePen); + painter.setBrush(mHandleColor); } + painter.drawRect(static_cast(pathPoint.x() - HANDLE_WIDTH/2), + static_cast(pathPoint.y() - HANDLE_WIDTH/2), + HANDLE_WIDTH, HANDLE_WIDTH); + painter.restore(); } diff --git a/core_lib/src/camerapainter.h b/core_lib/src/camerapainter.h index 768d602156..6b54bc8eb3 100644 --- a/core_lib/src/camerapainter.h +++ b/core_lib/src/camerapainter.h @@ -21,6 +21,7 @@ GNU General Public License for more details. #include #include #include +#include #include "onionskinpainteroptions.h" #include "onionskinsubpainter.h" @@ -31,6 +32,7 @@ class Object; class QPalette; class QPixmap; class QRect; +class KeyFrame; class CameraPainter { @@ -49,9 +51,10 @@ class CameraPainter void initializePainter(QPainter& painter, QPixmap& pixmap) const; void paintVisuals(QPainter& painter) const; void paintBorder(QPainter& painter, const QTransform& camTransform, const QRect& camRect) const; - void paintInterpolations(QPainter& painter, const LayerCamera* cameraLayer) const; + void paintOnionSkinning(QPainter& painter, const LayerCamera* cameraLayer) const; + void paintInterpolations(QPainter& painter, const LayerCamera* cameraLayer, const KeyFrame* keyframe) const; void paintHandles(QPainter& painter, const QTransform& camTransform, const QRect& cameraRect, const QPointF translation, const qreal scale, const qreal rotation, bool hollowHandles) const; - void paintPath(QPainter& painter, const LayerCamera* cameraLayer, const int frameIndex, const QPointF& pathPoint, bool hollowHandle) const; + void paintControlPoint(QPainter& painter, const LayerCamera* cameraLayer, const int frameIndex, const QPointF& pathPoint, bool hollowHandle) const; const Object* mObject = nullptr; QPixmap* mCanvas = nullptr; @@ -71,7 +74,9 @@ class CameraPainter bool mIsPlaying = false; bool mShowHandles = false; + QPen mHandlePen; QColor mHandleColor; + QColor mHandleDisabledColor; QColor mHandleTextColor; }; diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index 5aa7aa4129..649428c592 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -143,6 +143,7 @@ void ScribbleArea::settingUpdated(SETTING setting) case SETTING::INVISIBLE_LINES: case SETTING::OUTLINES: case SETTING::ONION_TYPE: + case SETTING::ONION_WHILE_PLAYBACK: invalidateAllCache(); break; case SETTING::QUICK_SIZING: