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
overlaypainter.cpp
1#include "overlaypainter.h"
2
3#include "layercamera.h"
4#include "camera.h"
5#include "layer.h"
6#include "util.h"
7
8Q_CONSTEXPR static int LEFT_ANGLE_OFFSET = 90;
9Q_CONSTEXPR static int RIGHT_ANGLE_OFFSET = -90;
10Q_CONSTEXPR static int HANDLE_WIDTH = 12;
11
12OverlayPainter::OverlayPainter()
13{
14}
15
16void OverlayPainter::initializePainter(QPainter& painter)
17{
18 painter.setCompositionMode(QPainter::CompositionMode_Difference);
19 QPen pen(QColor(180, 220, 255));
20 pen.setCosmetic(true);
21 painter.setPen(pen);
22 painter.setBrush(Qt::NoBrush);
23}
24
25void OverlayPainter::preparePainter(const LayerCamera* cameraLayer, const QPalette& palette)
26{
27 mPalette = palette;
28 mCameraLayer = cameraLayer;
29}
30
31void OverlayPainter::setViewTransform(const QTransform view)
32{
33 mViewTransform = view;
34}
35
36void OverlayPainter::paint(QPainter &painter, const QRect& viewport)
37{
38 if (mCameraLayer == nullptr) { return; }
39
40 painter.save();
41 initializePainter(painter);
42
43 QTransform camTransform = mCameraLayer->getViewAtFrame(mOptions.nFrameIndex);
44 QRect cameraRect = mCameraLayer->getViewRect();
45 Camera* camera = mCameraLayer->getLastCameraAtFrame(mOptions.nFrameIndex, 0);
46
47 if (camera == nullptr) { return; }
48
49
50 painter.setWorldTransform(mViewTransform);
51 if (mOptions.bCenter)
52 {
53 paintOverlayCenter(painter, camTransform, cameraRect);
54 }
55 if (mOptions.bThirds)
56 {
57 paintOverlayThirds(painter, camTransform, cameraRect);
58 }
59 if (mOptions.bGoldenRatio)
60 {
61 paintOverlayGolden(painter, camTransform, cameraRect);
62 }
63 if (mOptions.bSafeArea)
64 {
65 paintOverlaySafeAreas(painter, *camera, camTransform, cameraRect);
66 }
67
68 const QRect mappedViewport = mViewTransform.inverted().mapRect(viewport);
69 if (mOptions.bPerspective1)
70 {
71 paintOverlayPerspectiveOnePoint(painter, mappedViewport, camTransform);
72 }
73 if (mOptions.bPerspective2 || mOptions.bPerspective3)
74 {
75 paintOverlayPerspectiveTwoPoints(painter, mappedViewport, *camera, camTransform);
76 }
77 if (mOptions.bPerspective3)
78 {
79 paintOverlayPerspectiveThreePoints(painter, mappedViewport, *camera, camTransform);
80 }
81
82 if (mOptions.bGrid)
83 {
84 paintGrid(painter);
85 }
86
87 painter.restore();
88}
89
90void OverlayPainter::paintOverlayCenter(QPainter &painter, const QTransform& camTransform, const QRect& camRect) const
91{
92 painter.save();
93 painter.setCompositionMode(QPainter::RasterOp_NotSourceAndNotDestination);
94
95 QPen pen(Qt::DashLine);
96 qreal space = 10;
97 QVector<qreal> dashes;
98 dashes << 10 << space << 10 << space << 10 << space;
99 pen.setDashPattern(dashes);
100 pen.setCosmetic(true);
101 painter.setPen(pen);
102 painter.setBrush(Qt::NoBrush);
103 painter.setRenderHint(QPainter::Antialiasing, false);
104
105 QPolygon poly = camTransform.inverted().mapToPolygon(camRect);
106 QPoint centerTop = QLineF(poly.at(0), poly.at(1)).pointAt(0.5).toPoint();
107 QPoint centerBottom = QLineF(poly.at(2), poly.at(3)).pointAt(0.5).toPoint();
108 QPoint centerLeft = QLineF(poly.at(0), poly.at(3)).pointAt(0.5).toPoint();
109 QPoint centerRight = QLineF(poly.at(1), poly.at(2)).pointAt(0.5).toPoint();
110 painter.drawLine(QLineF(centerTop, centerBottom).pointAt(0.4).toPoint(),
111 QLineF(centerTop, centerBottom).pointAt(0.6).toPoint());
112 painter.drawLine(QLineF(centerLeft, centerRight).pointAt(0.4).toPoint(),
113 QLineF(centerLeft, centerRight).pointAt(0.6).toPoint());
114
115 painter.restore();
116}
117
118void OverlayPainter::paintOverlayThirds(QPainter &painter, const QTransform& camTransform, const QRect& camRect) const
119{
120 painter.save();
121 painter.setCompositionMode(QPainter::RasterOp_NotSourceAndNotDestination);
122
123 QPen pen(Qt::DashLine);
124 qreal space = 10;
125 QVector<qreal> dashes;
126 dashes << 10 << space << 10 << space << 10 << space;
127 pen.setDashPattern(dashes);
128 pen.setCosmetic(true);
129 painter.setPen(pen);
130 painter.setBrush(Qt::NoBrush);
131 painter.setRenderHint(QPainter::Antialiasing, false);
132
133 QPolygon poly = camTransform.inverted().mapToPolygon(camRect);
134 QLineF topLine(poly.at(0), poly.at(1));
135 QLineF bottomLine(poly.at(3), poly.at(2));
136 QLineF leftLine(poly.at(0), poly.at(3));
137 QLineF rightLine(poly.at(1), poly.at(2));
138 painter.drawLine(topLine.pointAt(0.333).toPoint(), bottomLine.pointAt(0.333));
139 painter.drawLine(topLine.pointAt(0.667).toPoint(), bottomLine.pointAt(0.667));
140 painter.drawLine(leftLine.pointAt(0.333).toPoint(), rightLine.pointAt(0.333));
141 painter.drawLine(leftLine.pointAt(0.667).toPoint(), rightLine.pointAt(0.667));
142
143 painter.restore();
144}
145
146void OverlayPainter::paintOverlayGolden(QPainter &painter, const QTransform& camTransform, const QRect& camRect) const
147{
148 painter.save();
149 painter.setCompositionMode(QPainter::RasterOp_NotSourceAndNotDestination);
150
151 QPen pen(Qt::DashLine);
152 qreal space = 10;
153 QVector<qreal> dashes;
154 dashes << 10 << space << 10 << space << 10 << space;
155 pen.setDashPattern(dashes);
156 pen.setCosmetic(true);
157 painter.setPen(pen);
158 painter.setBrush(Qt::NoBrush);
159 painter.setRenderHint(QPainter::Antialiasing, false);
160
161 QPolygon poly = camTransform.inverted().mapToPolygon(camRect);
162 QLineF topLine(poly.at(0), poly.at(1));
163 QLineF bottomLine(poly.at(3), poly.at(2));
164 QLineF leftLine(poly.at(0), poly.at(3));
165 QLineF rightLine(poly.at(1), poly.at(2));
166 painter.drawLine(topLine.pointAt(0.382).toPoint(), bottomLine.pointAt(0.382));
167 painter.drawLine(topLine.pointAt(0.618).toPoint(), bottomLine.pointAt(0.618));
168 painter.drawLine(leftLine.pointAt(0.382).toPoint(), rightLine.pointAt(0.382));
169 painter.drawLine(leftLine.pointAt(0.618).toPoint(), rightLine.pointAt(0.618));
170
171 painter.restore();
172}
173
174void OverlayPainter::paintOverlaySafeAreas(QPainter &painter, const Camera& camera, const QTransform& camTransform, const QRect& camRect) const
175{
176 painter.save();
177 painter.setCompositionMode(QPainter::RasterOp_NotSourceAndNotDestination);
178 QPen pen(Qt::DashLine);
179 qreal space = 10;
180 QVector<qreal> dashes;
181 dashes << 10 << space << 10 << space << 10 << space;
182 pen.setDashPattern(dashes);
183 pen.setCosmetic(true);
184 painter.setPen(pen);
185 painter.setBrush(Qt::NoBrush);
186 painter.setRenderHint(QPainter::TextAntialiasing, true);
187
188 QPolygon poly = camTransform.inverted().mapToPolygon(camRect);
189 QLineF topLeftCrossLine(poly.at(0), poly.at(2));
190 QLineF bottomLeftCrossLine(poly.at(3), poly.at(1));
191
192 if (mOptions.bActionSafe)
193 {
194 int action = mOptions.nActionSafe;
195 painter.drawLine(topLeftCrossLine.pointAt((action / 2.0) / 100.0).toPoint(),
196 bottomLeftCrossLine.pointAt((100 - (action / 2.0)) / 100).toPoint());
197 painter.drawLine(topLeftCrossLine.pointAt((action / 2.0) / 100.0).toPoint(),
198 bottomLeftCrossLine.pointAt((action / 2.0) / 100).toPoint());
199 painter.drawLine(topLeftCrossLine.pointAt((100 - (action / 2.0)) / 100.0).toPoint(),
200 bottomLeftCrossLine.pointAt((100 - (action / 2.0)) / 100).toPoint());
201 painter.drawLine(topLeftCrossLine.pointAt((100 - (action / 2.0)) / 100.0).toPoint(),
202 bottomLeftCrossLine.pointAt((action / 2.0) / 100).toPoint());
203
204 if (mOptions.bShowSafeAreaHelperText)
205 {
206 painter.save();
207 QPointF topLeft = topLeftCrossLine.pointAt((action / 2.0) / 100 ).toPoint();
208
209 QTransform trans = QTransform::fromTranslate(topLeft.x(), topLeft.y());
210 QTransform rot = QTransform().rotate(-camera.rotation());
211 QTransform scale = QTransform::fromScale(camera.scaling(), camera.scaling());
212
213 QTransform t = scale.inverted() * rot * trans;
214 painter.setTransform(t, true);
215 painter.drawText(QPoint(), tr("Safe Action area %1 %").arg(action));
216 painter.restore();
217 }
218 }
219 if (mOptions.bTitleSafe)
220 {
221 int title = mOptions.nTitleSafe;
222 painter.drawLine(topLeftCrossLine.pointAt((title / 2.0) / 100.0).toPoint(),
223 bottomLeftCrossLine.pointAt((100 - (title / 2.0)) / 100).toPoint());
224 painter.drawLine(topLeftCrossLine.pointAt((title / 2.0) / 100.0).toPoint(),
225 bottomLeftCrossLine.pointAt((title / 2.0) / 100).toPoint());
226 painter.drawLine(topLeftCrossLine.pointAt((100 - (title / 2.0)) / 100.0).toPoint(),
227 bottomLeftCrossLine.pointAt((100 - (title / 2.0)) / 100).toPoint());
228 painter.drawLine(topLeftCrossLine.pointAt((100 - (title / 2.0)) / 100.0).toPoint(),
229 bottomLeftCrossLine.pointAt((title / 2.0) / 100).toPoint());
230
231 if (mOptions.bShowSafeAreaHelperText)
232 {
233 QPointF bottomLeft = bottomLeftCrossLine.pointAt((title / 2.0) / 100);
234 painter.save();
235
236 QTransform trans = QTransform::fromTranslate(bottomLeft.x(), bottomLeft.y());
237 QTransform rot = QTransform().rotate(-camera.rotation());
238 QTransform scale = QTransform::fromScale(camera.scaling(), camera.scaling());
239
240 QTransform t = scale.inverted() * rot * trans;
241 painter.setTransform(t, true);
242 painter.drawText(QPoint(), tr("Safe Title area %1 %").arg(title));
243 painter.restore();
244 }
245 }
246 painter.restore();
247}
248
249void OverlayPainter::paintOverlayPerspectiveOnePoint(QPainter& painter, const QRect& viewport, const QTransform& camTransform) const
250{
251 qreal degrees = static_cast<qreal>(mOptions.nOverlayAngle);
252 if (degrees == 7.0) { degrees = 7.5; }
253
254 QPointF singlePoint = camTransform.inverted().map(mOptions.mSinglePerspPoint);
255 QLineF angleLine(singlePoint.x(), singlePoint.y(), singlePoint.x() + 1, singlePoint.y());
256
257 QVector<QLineF> lines;
258 for (qreal angle = 0; angle < 180; angle += degrees)
259 {
260 angleLine.setAngle(angle);
261 lines.append(clipLine(angleLine, viewport, -qInf(), qInf()));
262 }
263
264 painter.save();
265 painter.setRenderHint(QPainter::Antialiasing, true);
266 painter.drawLines(lines);
267
268 if (mOptions.bShowHandle) {
269 singlePoint = mViewTransform.map(singlePoint);
270 painter.setWorldMatrixEnabled(false);
271 painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
272 painter.setPen(mPalette.color(QPalette::HighlightedText));
273 painter.setBrush(mPalette.color(QPalette::Highlight));
274 painter.drawEllipse(QRectF(singlePoint.x()-HANDLE_WIDTH*.5, singlePoint.y()-HANDLE_WIDTH*.5, HANDLE_WIDTH, HANDLE_WIDTH));
275 }
276
277 painter.restore();
278}
279
280void OverlayPainter::paintOverlayPerspectiveTwoPoints(QPainter& painter, const QRect& viewport, const Camera& camera, const QTransform& camTransform) const
281{
282 qreal degrees = static_cast<qreal>(mOptions.nOverlayAngle);
283 if (degrees == 7.0) { degrees = 7.5; }
284
285 QPointF leftPoint = camTransform.inverted().map(mOptions.mLeftPerspPoint);
286 QPointF rightPoint = camTransform.inverted().map(mOptions.mRightPerspPoint);
287 QLineF angleLineLeft(leftPoint.x(), leftPoint.y(), leftPoint.x() + 1, leftPoint.y());
288 QLineF angleLineRight(rightPoint.x(), rightPoint.y(), rightPoint.x() + 1, rightPoint.y());
289
290 QVector<QLineF> lines;
291 for (qreal angle = 0; angle <= 180; angle += degrees)
292 {
293 angleLineLeft.setAngle(LEFT_ANGLE_OFFSET - angle + camera.rotation());
294 angleLineRight.setAngle(RIGHT_ANGLE_OFFSET - angle + camera.rotation());
295 lines.append(clipLine(angleLineLeft, viewport, 0, qInf()));
296 lines.append(clipLine(angleLineRight, viewport, 0, qInf()));
297 }
298
299 painter.save();
300 painter.setRenderHint(QPainter::Antialiasing, true);
301 painter.drawLines(lines);
302
303 if (mOptions.bShowHandle) {
304 leftPoint = mViewTransform.map(leftPoint);
305 rightPoint = mViewTransform.map(rightPoint);
306 painter.setWorldMatrixEnabled(false);
307 painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
308 painter.setPen(mPalette.color(QPalette::HighlightedText));
309 painter.setBrush(mPalette.color(QPalette::Highlight));
310 painter.drawEllipse(QRectF(leftPoint.x()-HANDLE_WIDTH*.5, leftPoint.y()-HANDLE_WIDTH*.5, HANDLE_WIDTH,HANDLE_WIDTH));
311 painter.drawEllipse(QRectF(rightPoint.x()-HANDLE_WIDTH*.5, rightPoint.y()-HANDLE_WIDTH*.5, HANDLE_WIDTH, HANDLE_WIDTH));
312 }
313
314 painter.restore();
315}
316
317void OverlayPainter::paintOverlayPerspectiveThreePoints(QPainter& painter, const QRect& viewport, const Camera& camera, const QTransform& camTransform) const
318{
319 qreal degrees = static_cast<qreal>(mOptions.nOverlayAngle);
320 if (degrees == 7.0) { degrees = 7.5; }
321
322 QPointF middlePoint = camTransform.inverted().map(mOptions.mMiddlePerspPoint);
323 QLineF angleLine(middlePoint.x(), middlePoint.y(), middlePoint.x() + 1, middlePoint.y());
324
325 const int middleAngleOffset = mOptions.mLeftPerspPoint.y() < mOptions.mMiddlePerspPoint.y() ? 180 : 0;
326 QVector<QLineF> lines;
327 for (qreal angle = 0; angle <= 180; angle += degrees)
328 {
329 angleLine.setAngle(middleAngleOffset - angle + camera.rotation());
330 lines.append(clipLine(angleLine, viewport, 0, qInf()));
331 }
332
333 painter.save();
334 painter.setRenderHint(QPainter::Antialiasing, true);
335 painter.drawLines(lines);
336
337 if (mOptions.bShowHandle) {
338 middlePoint = mViewTransform.map(middlePoint);
339 painter.setWorldMatrixEnabled(false);
340 painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
341 painter.setPen(mPalette.color(QPalette::HighlightedText));
342 painter.setBrush(mPalette.color(QPalette::Highlight));
343 painter.drawEllipse(QRectF(middlePoint.x()-HANDLE_WIDTH*.5, middlePoint.y()-HANDLE_WIDTH*.5, HANDLE_WIDTH,HANDLE_WIDTH));
344 }
345
346 painter.restore();
347}
348
349void OverlayPainter::paintGrid(QPainter& painter) const
350{
351 painter.save();
352 int gridSizeW = mOptions.nGridSizeW;
353 int gridSizeH = mOptions.nGridSizeH;
354
355 QRectF rect = painter.viewport();
356 QRectF boundingRect = mViewTransform.inverted().mapRect(rect);
357
358 int left = round100(boundingRect.left(), gridSizeW) - gridSizeW;
359 int right = round100(boundingRect.right(), gridSizeW) + gridSizeW;
360 int top = round100(boundingRect.top(), gridSizeH) - gridSizeH;
361 int bottom = round100(boundingRect.bottom(), gridSizeH) + gridSizeH;
362
363 QPen pen(Qt::lightGray);
364 pen.setCosmetic(true);
365 painter.setPen(pen);
366 painter.setBrush(Qt::NoBrush);
367 painter.setRenderHint(QPainter::Antialiasing, false);
368 // draw vertical grid lines
369 for (int x = left; x < right; x += gridSizeW)
370 {
371 painter.drawLine(x, top, x, bottom);
372 }
373
374 // draw horizontal grid lines
375 for (int y = top; y < bottom; y += gridSizeH)
376 {
377 painter.drawLine(left, y, right, y);
378 }
379
380 painter.restore();
381}
382
383int OverlayPainter::round100(double f, int gridSize) const
384{
385 return static_cast<int>(f) / gridSize * gridSize;
386}
387
Camera
Definition: camera.h:25
LayerCamera
Definition: layercamera.h:30
QColor
QLineF
QLineF::pointAt
QPointF pointAt(qreal t) const const
QPainter
QPainter::CompositionMode_Difference
CompositionMode_Difference
QPainter::Antialiasing
Antialiasing
QPainter::drawEllipse
void drawEllipse(const QRectF &rectangle)
QPainter::drawLine
void drawLine(const QLineF &line)
QPainter::drawLines
void drawLines(const QLineF *lines, int lineCount)
QPainter::drawText
void drawText(const QPointF &position, const QString &text)
QPainter::restore
void restore()
QPainter::save
void save()
QPainter::setBrush
void setBrush(const QBrush &brush)
QPainter::setCompositionMode
void setCompositionMode(QPainter::CompositionMode mode)
QPainter::setPen
void setPen(const QColor &color)
QPainter::setRenderHint
void setRenderHint(QPainter::RenderHint hint, bool on)
QPainter::setTransform
void setTransform(const QTransform &transform, bool combine)
QPainter::setWorldMatrixEnabled
void setWorldMatrixEnabled(bool enable)
QPainter::setWorldTransform
void setWorldTransform(const QTransform &matrix, bool combine)
QPainter::viewport
QRect viewport() const const
QPalette
QPalette::HighlightedText
HighlightedText
QPalette::color
const QColor & color(QPalette::ColorGroup group, QPalette::ColorRole role) const const
QPen
QPoint
QPointF
QPointF::toPoint
QPoint toPoint() const const
QPointF::x
qreal x() const const
QPointF::y
qreal y() const const
QPolygon
QRect
QRectF
QRectF::bottom
qreal bottom() const const
QRectF::left
qreal left() const const
QRectF::right
qreal right() const const
QRectF::top
qreal top() const const
Qt::NoBrush
NoBrush
Qt::lightGray
lightGray
Qt::DashLine
DashLine
Qt::left
QTextStream & left(QTextStream &stream)
Qt::right
QTextStream & right(QTextStream &stream)
QTransform
QTransform::fromScale
QTransform fromScale(qreal sx, qreal sy)
QTransform::fromTranslate
QTransform fromTranslate(qreal dx, qreal dy)
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
QTransform::mapToPolygon
QPolygon mapToPolygon(const QRect &rectangle) const const
QTransform::rotate
QTransform & rotate(qreal angle, Qt::Axis axis)
QVector
QVector::append
void append(const T &value)
QVector::at
const T & at(int i) const const
Generated on Thu May 8 2025 04:47:53 for Pencil2D by doxygen 1.9.6 based on revision 4513250b1d5b1a3676ec0e67b06b7a885ceaae39