Pencil2D Animation
Download Community News Docs Contribute
  • Overview
  • Articles
  • Code
  •  
  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
  • File List
Loading...
Searching...
No Matches
  • core_lib
  • src
camerapainter.cpp
1/*
2
3Pencil2D - Traditional Animation Software
4Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
5Copyright (C) 2012-2020 Matthew Chiawen Chang
6
7This program is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public License
9as published by the Free Software Foundation; version 2 of the License.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16*/
17
18#include "camerapainter.h"
19
20#include <QPainter>
21#include <QPixmap>
22#include "object.h"
23#include "layercamera.h"
24#include "camera.h"
25#include "keyframe.h"
26
27#include "transform.h"
28
29#include "painterutils.h"
30
31CameraPainter::CameraPainter(QPixmap& canvas) : mCanvas(canvas)
32{
33 reset();
34}
35
36void CameraPainter::reset()
37{
38 mCameraPixmap = QPixmap(mCanvas.size());
39 mCameraPixmap.setDevicePixelRatio(mCanvas.devicePixelRatioF());
40 mCameraPixmap.fill(Qt::transparent);
41}
42
43void CameraPainter::resetCache()
44{
45 mCameraCacheValid = false;
46}
47
48void CameraPainter::preparePainter(const Object* object,
49 int layerIndex,
50 int frameIndex,
51 const QTransform& transform,
52 bool isPlaying,
53 LayerVisibility layerVisibility,
54 float relativeLayerOpacityThreshold,
55 qreal viewScale)
56{
57 mObject = object;
58 mCurrentLayerIndex = layerIndex;
59 mFrameIndex = frameIndex;
60 mViewTransform = transform;
61 mIsPlaying = isPlaying;
62 mLayerVisibility = layerVisibility;
63 mRelativeLayerOpacityThreshold = relativeLayerOpacityThreshold;
64 mViewScale = viewScale;
65}
66
67void CameraPainter::paint(const QRect& blitRect)
68{
69 QPainter painter;
70 initializePainter(painter, mCanvas, blitRect, false);
71 paintVisuals(painter, blitRect);
72
73 mCameraCacheValid = true;
74}
75
76void CameraPainter::paintCached(const QRect& blitRect)
77{
78 QPainter painter;
79 // As always, initialize the painter with the canvas image, as this is what we'll paint on
80 // In this case though because the canvas has already been painted, we're not interested in
81 // having the blitter clear the image again, as that would remove our previous painted data, ie. strokes...
82 initializePainter(painter, mCanvas, blitRect, false);
83 if (!mCameraCacheValid) {
84 paintVisuals(painter, blitRect);
85 painter.end();
86 mCameraCacheValid = true;
87 } else {
88 painter.setWorldMatrixEnabled(false);
89 painter.drawPixmap(mZeroPoint, mCameraPixmap);
90 painter.setWorldMatrixEnabled(true);
91 painter.end();
92 }
93}
94
95void CameraPainter::initializePainter(QPainter& painter, QPixmap& pixmap, const QRect& blitRect, bool blitEnabled)
96{
97 painter.begin(&pixmap);
98
99 if (blitEnabled) {
100 painter.setCompositionMode(QPainter::CompositionMode_Clear);
101 painter.fillRect(blitRect, Qt::transparent);
102 // Surface has been cleared and is ready to be painted on
103 painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
104 }
105
106 painter.setClipRect(blitRect);
107 painter.setWorldMatrixEnabled(true);
108 painter.setWorldTransform(mViewTransform);
109}
110
111void CameraPainter::paintVisuals(QPainter& painter, const QRect& blitRect)
112{
113 LayerCamera* cameraLayerBelow = static_cast<LayerCamera*>(mObject->getLayerBelow(mCurrentLayerIndex, Layer::CAMERA));
114
115 if (cameraLayerBelow == nullptr) { return; }
116
117 const Layer* currentLayer = mObject->getLayer(mCurrentLayerIndex);
118
119 if (mLayerVisibility == LayerVisibility::CURRENTONLY && currentLayer->type() != Layer::CAMERA) { return; }
120
121 QPainter visualsPainter;
122 initializePainter(visualsPainter, mCameraPixmap, blitRect, true);
123
124 if (!mIsPlaying || mOnionSkinOptions.enabledWhilePlaying) {
125
126 int startLayerI = 0;
127 int endLayerI = mObject->getLayerCount() - 1;
128 for (int i = startLayerI; i <= endLayerI; i++) {
129 Layer* layer = mObject->getLayer(i);
130 if (layer->type() != Layer::CAMERA) { continue; }
131
132 LayerCamera* cameraLayer = static_cast<LayerCamera*>(layer);
133
134 bool isCurrentLayer = cameraLayer == cameraLayerBelow;
135
136 visualsPainter.save();
137 visualsPainter.setOpacity(1);
138 if (mLayerVisibility == LayerVisibility::RELATED && !isCurrentLayer) {
139 visualsPainter.setOpacity(calculateRelativeOpacityForLayer(mCurrentLayerIndex, i, mRelativeLayerOpacityThreshold));
140 }
141
142 paintOnionSkinning(visualsPainter, cameraLayer);
143
144 visualsPainter.restore();
145 }
146 }
147
148 if (!cameraLayerBelow->visible()) { return; }
149
150 QTransform camTransform = cameraLayerBelow->getViewAtFrame(mFrameIndex);
151 QRect cameraRect = cameraLayerBelow->getViewRect();
152 paintBorder(visualsPainter, camTransform, cameraRect);
153
154 painter.setWorldMatrixEnabled(false);
155 painter.drawPixmap(mZeroPoint, mCameraPixmap);
156}
157
158void CameraPainter::paintBorder(QPainter& painter, const QTransform& camTransform, const QRect& camRect)
159{
160 painter.save();
161 QRect viewRect = painter.viewport();
162
163 painter.setOpacity(1.0);
164 painter.setWorldMatrixEnabled(true);
165 painter.setPen(Qt::NoPen);
166 painter.setBrush(QColor(0, 0, 0, 80));
167 painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
168
169 QTransform viewInverse = mViewTransform.inverted();
170 QRect boundingRect = viewInverse.mapRect(viewRect);
171
172 QPolygon camPoly = camTransform.inverted().map(QPolygon(camRect));
173 QPolygon boundingRectPoly = boundingRect;
174 QPolygon visibleCanvasPoly = boundingRectPoly.subtracted(camPoly);
175
176 painter.drawPolygon(visibleCanvasPoly);
177
178 painter.restore();
179}
180
181void CameraPainter::paintOnionSkinning(QPainter& painter, const LayerCamera* cameraLayer)
182{
183 QPen onionSkinPen;
184
185 painter.save();
186 painter.setBrush(Qt::NoBrush);
187 painter.setWorldMatrixEnabled(false);
188
189 onionSkinPen.setStyle(Qt::PenStyle::DashLine);
190 mOnionSkinPainter.paint(painter, cameraLayer, mOnionSkinOptions, mFrameIndex, [&] (OnionSkinPaintState state, int onionSkinNumber) {
191
192 const QTransform& cameraTransform = cameraLayer->getViewAtFrame(onionSkinNumber);
193 const QPolygonF& cameraPolygon = Transform::mapToWorldPolygon(cameraTransform, mViewTransform, cameraLayer->getViewRect());
194 if (state == OnionSkinPaintState::PREV) {
195
196 if (mOnionSkinOptions.colorizePrevFrames) {
197 onionSkinPen.setColor(Qt::red);
198 }
199
200 painter.setPen(onionSkinPen);
201 painter.drawPolygon(cameraPolygon);
202 } else if (state == OnionSkinPaintState::NEXT) {
203 if (mOnionSkinOptions.colorizeNextFrames) {
204 onionSkinPen.setColor(Qt::blue);
205 }
206
207 painter.setPen(onionSkinPen);
208 painter.drawPolygon(cameraPolygon);
209 } else if (state == OnionSkinPaintState::CURRENT) {
210 painter.save();
211 painter.setPen(Qt::black);
212 painter.drawPolygon(cameraPolygon);
213 painter.restore();
214 }
215 });
216 painter.restore();
217}
LayerCamera
Definition: layercamera.h:30
Layer
Definition: layer.h:33
Object
Definition: object.h:42
QColor
QPaintDevice::devicePixelRatioF
qreal devicePixelRatioF() const const
QPainter
QPainter::CompositionMode_Clear
CompositionMode_Clear
QPainter::begin
bool begin(QPaintDevice *device)
QPainter::drawPixmap
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
QPainter::drawPolygon
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
QPainter::end
bool end()
QPainter::fillRect
void fillRect(const QRectF &rectangle, const QBrush &brush)
QPainter::restore
void restore()
QPainter::save
void save()
QPainter::setBrush
void setBrush(const QBrush &brush)
QPainter::setClipRect
void setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
QPainter::setCompositionMode
void setCompositionMode(QPainter::CompositionMode mode)
QPainter::setOpacity
void setOpacity(qreal opacity)
QPainter::setPen
void setPen(const QColor &color)
QPainter::setWorldMatrixEnabled
void setWorldMatrixEnabled(bool enable)
QPainter::setWorldTransform
void setWorldTransform(const QTransform &matrix, bool combine)
QPainter::viewport
QRect viewport() const const
QPen
QPen::setColor
void setColor(const QColor &color)
QPen::setStyle
void setStyle(Qt::PenStyle style)
QPixmap
QPixmap::fill
void fill(const QColor &color)
QPixmap::setDevicePixelRatio
void setDevicePixelRatio(qreal scaleFactor)
QPixmap::size
QSize size() const const
QPolygon
QPolygon::subtracted
QPolygon subtracted(const QPolygon &r) const const
QPolygonF
QRect
Qt::NoBrush
NoBrush
Qt::transparent
transparent
Qt::NoPen
NoPen
Qt::reset
QTextStream & reset(QTextStream &stream)
QTransform
QTransform::inverted
QTransform inverted(bool *invertible) const const
QTransform::map
QPoint map(const QPoint &point) const const
QTransform::mapRect
QRect mapRect(const QRect &rectangle) const const
Generated on Thu May 8 2025 04:47:53 for Pencil2D by doxygen 1.9.6 based on revision 4513250b1d5b1a3676ec0e67b06b7a885ceaae39