Pencil2D Animation
Download Community News Docs Contribute

core_lib/src/structure/layercamera.cpp Source File

  • Main Page
  • Related Pages
  • Classes
  • Files
  •  
  • File List
Loading...
Searching...
No Matches
  • core_lib
  • src
  • structure
layercamera.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#include "layercamera.h"
18
19#include <QSettings>
20#include <QEasingCurve>
21
22#include "camera.h"
23#include "pencildef.h"
24
25LayerCamera::LayerCamera(Object* object) : Layer(object, Layer::CAMERA)
26{
27 setName(tr("Camera Layer"));
28
29 QSettings settings(PENCIL2D, PENCIL2D);
30 mFieldW = settings.value("FieldW").toInt();
31 mFieldH = settings.value("FieldH").toInt();
32 if (mFieldW < 2 || mFieldH < 2)
33 {
34 mFieldW = 800;
35 mFieldH = 600;
36 }
37 viewRect = QRect(QPoint(-mFieldW / 2, -mFieldH / 2), QSize(mFieldW, mFieldH));
38}
39
40LayerCamera::~LayerCamera()
41{
42}
43
44bool LayerCamera::addKeyFrame(int position, KeyFrame *pKeyFrame)
45{
46 bool keyAdded = Layer::addKeyFrame(position, pKeyFrame);
47 if (keyAdded) {
48 splitControlPointIfNeeded(position);
49 }
50 return keyAdded;
51}
52
53bool LayerCamera::removeKeyFrame(int position)
54{
55 mergeControlPointIfNeeded(position);
56 return Layer::removeKeyFrame(position);;
57}
58
59Camera* LayerCamera::getCameraAtFrame(int frameNumber) const
60{
61 return static_cast<Camera*>(getKeyFrameAt(frameNumber));
62}
63
64Camera* LayerCamera::getLastCameraAtFrame(int frameNumber, int increment) const
65{
66 return static_cast<Camera*>(getLastKeyFrameAtPosition(frameNumber + increment));
67}
68
69QTransform LayerCamera::getViewAtFrame(int frameNumber) const
70{
71 if (keyFrameCount() == 0)
72 {
73 return QTransform();
74 }
75
76 // IMO: There should always be a keyframe on frame 1 on the Camera layer! (David)
77 if (frameNumber < firstKeyFramePosition())
78 {
79 frameNumber = firstKeyFramePosition();
80 }
81
82 Camera* camera1 = static_cast<Camera*>(getLastKeyFrameAtPosition(frameNumber));
83
84 int nextFrame = getNextKeyFramePosition(frameNumber);
85 Camera* camera2 = static_cast<Camera*>(getLastKeyFrameAtPosition(nextFrame));
86
87 if (camera1 == nullptr && camera2 == nullptr)
88 {
89 return QTransform();
90 }
91 else if (camera1 == nullptr && camera2 != nullptr)
92 {
93 return camera2->getView();
94 }
95 else if (camera2 == nullptr && camera1 != nullptr)
96 {
97 return camera1->getView();
98 }
99
100 if (camera1->compare(*camera2))
101 {
102 return camera1->getView();
103 }
104
105 double frame1 = camera1->pos();
106 double frame2 = camera2->pos();
107
108 // interpolation
109 qreal percent = getInterpolationPercent(camera1->getEasingType(), (frameNumber - frame1) / (frame2 - frame1));
110 auto lerp = [](double f1, double f2, double percent) -> double
111 {
112 return f1 * (1.0 - percent) + f2 * percent;
113 };
114
115 QPointF controlPoint = camera1->getPathControlPoint();
116 if (!camera1->pathControlPointMoved()) {
117 controlPoint = getCenteredPathPoint(frame1);
118 }
119
120 const QPointF& point = getBezierPoint(camera1->translation(), camera2->translation(),
121 -controlPoint, percent);
122
123 double dx = point.x();
124 double dy = point.y();
125 double r = lerp(camera1->rotation(), camera2->rotation(), percent);
126 double s = lerp(camera1->scaling(), camera2->scaling(), percent);
127
128 QTransform camTransform;
129 camTransform.scale(s, s);
130 camTransform.rotate(r);
131 camTransform.translate(dx, dy);
132
133 return camTransform;
134}
135
136void LayerCamera::linearInterpolateTransform(Camera* cam)
137{
138 if (keyFrameCount() == 0)
139 return;
140
141 int frameNumber = cam->pos();
142 Camera* camera1 = static_cast<Camera*>(getLastKeyFrameAtPosition(frameNumber - 1));
143
144 int nextFrame = getNextKeyFramePosition(frameNumber);
145 Camera* camera2 = static_cast<Camera*>(getLastKeyFrameAtPosition(nextFrame));
146
147 if (camera1 == nullptr && camera2 == nullptr)
148 {
149 return; // do nothing
150 }
151
152 else if (camera1 == nullptr && camera2 != nullptr)
153 {
154 return cam->assign(*camera2);
155 }
156
157 else if (camera2 == nullptr && camera1 != nullptr)
158 {
159 return cam->assign(*camera1);
160 }
161
162 if (camera1->compare(*camera2))
163 {
164 return cam->assign(*camera1);
165 }
166
167 double frame1 = camera1->pos();
168 double frame2 = camera2->pos();
169
170 // interpolation
171 qreal percent = getInterpolationPercent(camera1->getEasingType(), (frameNumber - frame1)/ (frame2 - frame1));
172
173 auto lerp = [](double f1, double f2, double percent) -> double
174 {
175 return f1 * (1.0 - percent) + f2 * percent;
176 };
177
178 QPointF controlPoint = camera1->getPathControlPoint();
179 if (!camera1->pathControlPointMoved()) {
180 controlPoint = getCenteredPathPoint(frame1);
181 }
182
183 QPointF point = getBezierPoint(camera1->translation(), camera2->translation(),
184 -controlPoint, percent);
185 double dx = point.x();
186 double dy = point.y();
187 double r = lerp(camera1->rotation(), camera2->rotation(), percent);
188 double s = lerp(camera1->scaling(), camera2->scaling(), percent);
189
190 cam->translate(dx, dy);
191 cam->rotate(r);
192 cam->scale(s);
193}
194
195qreal LayerCamera::getInterpolationPercent(CameraEasingType type, qreal percent) const
196{
197 QEasingCurve easing;
198
199 switch (type)
200 {
201 case CameraEasingType::LINEAR : easing.setType(QEasingCurve::Linear); break;
202 case CameraEasingType::INQUAD : easing.setType(QEasingCurve::InQuad); break;
203 case CameraEasingType::OUTQUAD : easing.setType(QEasingCurve::OutQuad); break;
204 case CameraEasingType::INOUTQUAD : easing.setType(QEasingCurve::InOutQuad); break;
205 case CameraEasingType::OUTINQUAD : easing.setType(QEasingCurve::OutInQuad); break;
206 case CameraEasingType::INCUBIC : easing.setType(QEasingCurve::InCubic); break;
207 case CameraEasingType::OUTCUBIC : easing.setType(QEasingCurve::OutCubic); break;
208 case CameraEasingType::INOUTCUBIC : easing.setType(QEasingCurve::InOutCubic); break;
209 case CameraEasingType::OUTINCUBIC : easing.setType(QEasingCurve::OutInCubic); break;
210 case CameraEasingType::INQUART : easing.setType(QEasingCurve::InQuart); break;
211 case CameraEasingType::OUTQUART : easing.setType(QEasingCurve::OutQuart); break;
212 case CameraEasingType::INOUTQUART : easing.setType(QEasingCurve::InOutQuart); break;
213 case CameraEasingType::OUTINQUART : easing.setType(QEasingCurve::OutInQuart); break;
214 case CameraEasingType::INQUINT : easing.setType(QEasingCurve::InQuint); break;
215 case CameraEasingType::OUTQUINT : easing.setType(QEasingCurve::OutQuint); break;
216 case CameraEasingType::INOUTQUINT : easing.setType(QEasingCurve::InOutQuint); break;
217 case CameraEasingType::OUTINQUINT : easing.setType(QEasingCurve::OutInQuint); break;
218 case CameraEasingType::INSINE : easing.setType(QEasingCurve::InSine); break;
219 case CameraEasingType::OUTSINE : easing.setType(QEasingCurve::OutSine); break;
220 case CameraEasingType::INOUTSINE : easing.setType(QEasingCurve::InOutSine); break;
221 case CameraEasingType::OUTINSINE: easing.setType(QEasingCurve::OutInSine); break;
222 case CameraEasingType::INEXPO : easing.setType(QEasingCurve::InExpo); break;
223 case CameraEasingType::OUTEXPO : easing.setType(QEasingCurve::OutExpo); break;
224 case CameraEasingType::INOUTEXPO : easing.setType(QEasingCurve::InOutExpo); break;
225 case CameraEasingType::OUTINEXPO: easing.setType(QEasingCurve::OutInExpo); break;
226 case CameraEasingType::INCIRC : easing.setType(QEasingCurve::InCirc); break;
227 case CameraEasingType::OUTCIRC : easing.setType(QEasingCurve::OutCirc); break;
228 case CameraEasingType::INOUTCIRC : easing.setType(QEasingCurve::InOutCirc); break;
229 case CameraEasingType::OUTINCIRC: easing.setType(QEasingCurve::OutInCirc); break;
230 case CameraEasingType::INELASTIC: easing.setType(QEasingCurve::InElastic); break;
231 case CameraEasingType::OUTELASTIC: easing.setType(QEasingCurve::OutElastic); break;
232 case CameraEasingType::INOUTELASTIC: easing.setType(QEasingCurve::InOutElastic); break;
233 case CameraEasingType::OUTINELASTIC: easing.setType(QEasingCurve::OutInElastic); break;
234 case CameraEasingType::INBACK: easing.setType(QEasingCurve::InBack); break;
235 case CameraEasingType::OUTBACK: easing.setType(QEasingCurve::OutBack); break;
236 case CameraEasingType::INOUTBACK: easing.setType(QEasingCurve::InOutBack); break;
237 case CameraEasingType::OUTINBACK: easing.setType(QEasingCurve::OutInBack); break;
238 case CameraEasingType::INBOUNCE: easing.setType(QEasingCurve::InBounce); break;
239 case CameraEasingType::OUTBOUNCE: easing.setType(QEasingCurve::OutBounce); break;
240 case CameraEasingType::INOUTBOUNCE: easing.setType(QEasingCurve::InOutBounce); break;
241 case CameraEasingType::OUTINBOUNCE: easing.setType(QEasingCurve::OutInBounce); break;
242 default: Q_UNREACHABLE(); break;
243 }
244 return easing.valueForProgress(percent);
245}
246
247QPointF LayerCamera::getBezierPoint(const QPointF& first, const QPointF& last, const QPointF& pathPoint, qreal percent) const
248{
249 QLineF line1(first, pathPoint);
250 QLineF line2(pathPoint, last);
251 return QLineF(line1.pointAt(percent), line2.pointAt(percent)).pointAt(percent);
252}
253
254void LayerCamera::splitControlPointIfNeeded(int frame) const
255{
256 int next = getNextKeyFramePosition(frame);
257 int prev = getPreviousKeyFramePosition(frame);
258
259 // if inbetween frames
260 if (frame > prev && (frame > 1) && frame < next)
261 {
262 Camera* camFrame = getLastCameraAtFrame(frame, 0);
263 Camera* camPrev = getCameraAtFrame(prev);
264 Camera* camNext = getCameraAtFrame(next);
265 Q_ASSERT(camPrev && camFrame && camNext);
266
267 if (camPrev->pathControlPointMoved()) {
268 qreal t = static_cast<qreal>(frame - prev) / (next - prev);
269 QPointF previousControlPoint = camPrev->getPathControlPoint();
270
271 // Line from the current control point to the next frame
272 QLineF interpolatedLineCN = QLineF(previousControlPoint, -camNext->translation());
273
274 // Line from the previous frame to the current control point
275 QLineF interpolatedLinePC = QLineF(-camPrev->translation(), previousControlPoint);
276 // Place the new control points, so the curve is kept
277 camPrev->setPathControlPoint(interpolatedLinePC.pointAt(t));
278 camFrame->setPathControlPoint(interpolatedLineCN.pointAt(t));
279 camFrame->setPathControlPointMoved(true);
280 }
281 } else {
282 Camera* camPrev = getCameraAtFrame(prev);
283 camPrev->setPathControlPointMoved(false);
284 }
285}
286
287void LayerCamera::mergeControlPointIfNeeded(int frame) const
288{
289 int next = getNextKeyFramePosition(frame);
290 int prev = getPreviousKeyFramePosition(frame);
291
292 // if inbetween frames
293 if (frame > prev && (frame > 1) && frame < next)
294 {
295 Camera* camPrev = getCameraAtFrame(prev);
296 Camera* camFrame = getLastCameraAtFrame(frame, 0);
297 Camera* camNext = getCameraAtFrame(next);
298 Q_ASSERT(camPrev && camFrame && camNext);
299
300 if (camPrev->pathControlPointMoved()) {
301
302 // Line from the current control point to the next frame
303 const QLineF& interpolatedLineCN = QLineF(camFrame->getPathControlPoint(), -camNext->translation());
304
305 // Line from the previous frame translation to previous control point
306 const QLineF& interpolatedLinePC = QLineF(-camPrev->translation(), camPrev->getPathControlPoint());
307
308 QPointF mergedCPoint;
309#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
310 auto intersection = interpolatedLinePC.intersects(interpolatedLineCN, &mergedCPoint);
311#else
312 auto intersection = interpolatedLinePC.intersect(interpolatedLineCN, &mergedCPoint);
313#endif
314 // Try to recover the control point if the distance is within the threshold, otherwise do nothing
315 if (intersection == QLineF::UnboundedIntersection &&
316 QLineF(camFrame->getPathControlPoint(), mergedCPoint).length() < mControlPointMergeThreshold)
317 {
318 camPrev->setPathControlPoint(mergedCPoint);
319 camPrev->setPathControlPointMoved(true);
320 } else if (intersection == QLineF::NoIntersection) {
321 camPrev->setPathControlPointMoved(false);
322 }
323 }
324 }
325}
326
327QRect LayerCamera::getViewRect() const
328{
329 return viewRect;
330}
331
332QSize LayerCamera::getViewSize() const
333{
334 return viewRect.size();
335}
336
337void LayerCamera::setViewRect(QRect newViewRect)
338{
339 viewRect = newViewRect;
340}
341
342void LayerCamera::setCameraEasingAtFrame(CameraEasingType type, int frame) const
343{
344 Camera* camera = getLastCameraAtFrame(frame, 0);
345 camera->setEasingType(type);
346 camera->updateViewTransform();
347}
348
349void LayerCamera::resetCameraAtFrame(CameraFieldOption type, int frame) const
350{
351 int frameToModify = frame;
352 if (!keyExists(frame)) {
353 frameToModify = getPreviousKeyFramePosition(frame);
354 }
355 Camera* camera = getLastCameraAtFrame(frameToModify, 0);
356
357 switch (type)
358 {
359 case CameraFieldOption::RESET_FIELD:
360 camera->resetTransform();
361 break;
362 case CameraFieldOption::RESET_TRANSLATION:
363 camera->translate(QPoint(0,0));
364 break;
365 case CameraFieldOption::RESET_SCALING:
366 camera->scale(1.0);
367 break;
368 case CameraFieldOption::RESET_ROTATION:
369 camera->rotate(0.0);
370 break;
371 case CameraFieldOption::ALIGN_HORIZONTAL: {
372 qreal otherYCoord = camera->translation().y();
373 Camera* nextCam = getCameraAtFrame(getNextKeyFramePosition(frameToModify));
374 nextCam->translate(nextCam->translation().x(), otherYCoord);
375 camera->setPathControlPointMoved(false);
376 break;
377 }
378 case CameraFieldOption::ALIGN_VERTICAL: {
379 qreal otherXCoord = camera->translation().x();
380 Camera* nextCam = getCameraAtFrame(getNextKeyFramePosition(frameToModify));
381 nextCam->translate(otherXCoord, nextCam->translation().y());
382 camera->setPathControlPointMoved(false);
383 break;
384 }
385 case CameraFieldOption::HOLD_FRAME: {
386
387 if (getMaxKeyFramePosition() == camera->pos()) { return; }
388
389 QPointF translation = camera->translation();
390 qreal rotation = camera->rotation();
391 qreal scaling = camera->scaling();
392 camera->setPathControlPointMoved(false);
393 Camera* nextCamera = getLastCameraAtFrame(getNextKeyFramePosition(frame), 0);
394 nextCamera->translate(translation);
395 nextCamera->scale(scaling);
396 nextCamera->rotate(rotation);
397 nextCamera->setPathControlPointMoved(false);
398 break;
399 }
400 default:
401 Q_UNREACHABLE();
402 break;
403 }
404
405 if (type != CameraFieldOption::RESET_SCALING && type != CameraFieldOption::RESET_ROTATION) {
406 setPathMovedAtFrame(frame - 1, false);
407 }
408
409 camera->updateViewTransform();
410}
411
412void LayerCamera::updateDotColor(DotColorType color)
413{
414 switch (color)
415 {
416 case DotColorType::RED:
417 mDotColor = Qt::red;
418 break;
419 case DotColorType::GREEN:
420 mDotColor = Qt::green;
421 break;
422 case DotColorType::BLUE:
423 mDotColor = Qt::blue;
424 break;
425 case DotColorType::BLACK:
426 mDotColor = Qt::black;
427 break;
428 case DotColorType::WHITE:
429 mDotColor = Qt::white;
430 break;
431 }
432 mDotColorType = color;
433}
434
435QString LayerCamera::getInterpolationTextAtFrame(int frame) const
436{
437 Camera* camera = getLastCameraAtFrame(frame, 0);
438 return getInterpolationText(camera->getEasingType());
439}
440
441QPointF LayerCamera::getPathControlPointAtFrame(int frame) const
442{
443 Camera* camera = getCameraAtFrame(getPreviousKeyFramePosition(frame));
444 Q_ASSERT(camera);
445
446 return camera->getPathControlPoint();
447}
448
449bool LayerCamera::hasSameTranslation(int frame1, int frame2) const
450{
451 Camera* camera1 = getCameraAtFrame(frame1);
452 Camera* camera2 = getCameraAtFrame(frame2);
453
454 if (camera1 == nullptr)
455 {
456 return false;
457 }
458 else if (camera2 == nullptr)
459 {
460 return false;
461 }
462
463 return camera1->translation() == camera2->translation();
464}
465
466QList<QPointF> LayerCamera::getBezierPointsAtFrame(int frame) const
467{
468 QList<QPointF> points;
469 int prevFrame = getPreviousKeyFramePosition(frame);
470 int nextFrame = getNextKeyFramePosition(frame);
471 if (prevFrame < nextFrame)
472 {
473 Camera* prevCam = getCameraAtFrame(prevFrame);
474 Camera* nextCam = getCameraAtFrame(nextFrame);
475 points.append(QPointF(-prevCam->translation()));
476 if (prevCam->pathControlPointMoved()) {
477 points.append(QPointF(prevCam->getPathControlPoint()));
478 } else {
479 points.append(QPointF(getCenteredPathPoint(prevFrame)));
480 }
481 points.append(QPointF(-nextCam->translation()));
482 }
483 return points;
484}
485
486QPointF LayerCamera::getCenteredPathPoint(int frame) const
487{
488 if (!keyExists(frame) || frame == getMaxKeyFramePosition())
489 frame = getPreviousKeyFramePosition(frame);
490 int nextFrame = getNextKeyFramePosition(frame);
491 Camera* cam1 = getCameraAtFrame(frame);
492 Camera* cam2 = getCameraAtFrame(nextFrame);
493
494 if (cam1 && cam2 == nullptr) {
495 return -cam1->translation();
496 } else if (cam2 && cam1 == nullptr) {
497 return -cam2->translation();
498 } else if (cam1 == nullptr && cam2 == nullptr) {
499 return QPointF();
500 }
501 return QLineF(-cam1->translation(), -cam2->translation()).pointAt(0.5);
502}
503
504void LayerCamera::setPathMovedAtFrame(int frame, bool moved) const
505{
506 Camera* cam = getLastCameraAtFrame(frame, 0);
507 Q_ASSERT(cam);
508
509 cam->setPathControlPointMoved(moved);
510}
511
512void LayerCamera::updatePathControlPointAtFrame(const QPointF& point, int frame) const
513{
514 Camera* camera = getLastCameraAtFrame(frame, 0);
515 Q_ASSERT(camera);
516
517 camera->setPathControlPoint(point);
518 camera->setPathControlPointMoved(true);
519}
520
521void LayerCamera::loadImageAtFrame(int frameNumber, qreal dx, qreal dy, qreal rotate, qreal scale, CameraEasingType easing, const QPointF& pathPoint, bool pathMoved)
522{
523 if (keyExists(frameNumber))
524 {
525 removeKeyFrame(frameNumber);
526 }
527 Camera* camera = new Camera(QPointF(dx, dy), rotate, scale);
528 camera->setPos(frameNumber);
529 camera->setEasingType(easing);
530 if (pathMoved) {
531 camera->setPathControlPoint(pathPoint);
532 camera->setPathControlPointMoved(pathMoved);
533 }
534 loadKey(camera);
535}
536
537Status LayerCamera::saveKeyFrameFile(KeyFrame*, QString)
538{
539 return Status::OK;
540}
541
542KeyFrame* LayerCamera::createKeyFrame(int position, Object*)
543{
544 Camera* c = new Camera;
545 c->setPos(position);
546 c->setEasingType(CameraEasingType::LINEAR);
547 linearInterpolateTransform(c);
548 c->setPathControlPoint(c->translation());
549 return c;
550}
551
552QDomElement LayerCamera::createDomElement(QDomDocument& doc) const
553{
554 QDomElement layerElem = createBaseDomElement(doc);
555 layerElem.setAttribute("width", viewRect.width());
556 layerElem.setAttribute("height", viewRect.height());
557
558 if (mShowPath) {
559 layerElem.setAttribute("showPath", mShowPath);
560 }
561
562 if (mDotColorType != DotColorType::RED) {
563 layerElem.setAttribute("pathColorType", static_cast<int>(mDotColorType));
564 }
565
566 foreachKeyFrame([&](KeyFrame* pKeyFrame)
567 {
568 Camera* camera = static_cast<Camera*>(pKeyFrame);
569 QDomElement keyTag = doc.createElement("camera");
570 keyTag.setAttribute("frame", camera->pos());
571
572 keyTag.setAttribute("r", camera->rotation());
573 keyTag.setAttribute("s", camera->scaling());
574 keyTag.setAttribute("dx", camera->translation().x());
575 keyTag.setAttribute("dy", camera->translation().y());
576
577 if (camera->getEasingType() != CameraEasingType::LINEAR) {
578 keyTag.setAttribute("easing", static_cast<int>(camera->getEasingType()));
579 }
580 if (camera->pathControlPointMoved()) {
581 keyTag.setAttribute("pathCPX", camera->getPathControlPoint().x());
582 keyTag.setAttribute("pathCPY", camera->getPathControlPoint().y());
583 }
584 layerElem.appendChild(keyTag);
585 });
586
587 return layerElem;
588}
589
590void LayerCamera::loadDomElement(const QDomElement& element, QString dataDirPath, ProgressCallback progressStep)
591{
592 Q_UNUSED(dataDirPath)
593 Q_UNUSED(progressStep)
594
595 this->loadBaseDomElement(element);
596
597 int width = element.attribute("width").toInt();
598 int height = element.attribute("height").toInt();
599 mShowPath = element.attribute("showPath").toInt();
600 updateDotColor(static_cast<DotColorType>(element.attribute("pathColorType").toInt()));
601 viewRect = QRect(-width / 2, -height / 2, width, height);
602
603 QDomNode imageTag = element.firstChild();
604 while (!imageTag.isNull())
605 {
606 QDomElement imageElement = imageTag.toElement();
607 if (!imageElement.isNull())
608 {
609 if (imageElement.tagName() == "camera")
610 {
611 int frame = imageElement.attribute("frame").toInt();
612
613 qreal rotate = imageElement.attribute("r", "0").toDouble();
614 qreal scale = imageElement.attribute("s", "1").toDouble();
615 qreal dx = imageElement.attribute("dx", "0").toDouble();
616 qreal dy = imageElement.attribute("dy", "0").toDouble();
617 CameraEasingType easing = static_cast<CameraEasingType>(imageElement.attribute("easing", "0").toInt());
618 qreal pathX = imageElement.attribute("pathCPX", "0").toDouble();
619 qreal pathY = imageElement.attribute("pathCPY", "0").toDouble();
620
621 bool pathMoved = pathX != 0 || pathY != 0;
622
623 loadImageAtFrame(frame, dx, dy, rotate, scale, easing, QPointF(pathX, pathY), pathMoved);
624 }
625 }
626 imageTag = imageTag.nextSibling();
627 }
628}
Camera
Definition: camera.h:25
KeyFrame
Definition: keyframe.h:30
Layer
Definition: layer.h:38
Object
Definition: object.h:42
Status
Definition: pencilerror.h:40
QDomDocument
QDomDocument::createElement
QDomElement createElement(const QString &tagName)
QDomElement
QDomElement::attribute
QString attribute(const QString &name, const QString &defValue) const const
QDomElement::setAttribute
void setAttribute(const QString &name, const QString &value)
QDomElement::tagName
QString tagName() const const
QDomNode
QDomNode::appendChild
QDomNode appendChild(const QDomNode &newChild)
QDomNode::firstChild
QDomNode firstChild() const const
QDomNode::isNull
bool isNull() const const
QDomNode::nextSibling
QDomNode nextSibling() const const
QDomNode::toElement
QDomElement toElement() const const
QEasingCurve
QEasingCurve::Linear
Linear
QEasingCurve::setType
void setType(QEasingCurve::Type type)
QEasingCurve::valueForProgress
qreal valueForProgress(qreal progress) const const
QLineF::UnboundedIntersection
UnboundedIntersection
QLineF::intersect
QLineF::IntersectType intersect(const QLineF &line, QPointF *intersectionPoint) const const
QLineF
QLineF::intersects
QLineF::IntersectionType intersects(const QLineF &line, QPointF *intersectionPoint) const const
QLineF::length
qreal length() const const
QLineF::pointAt
QPointF pointAt(qreal t) const const
QList
QList::append
void append(const T &value)
QPoint
QPointF
QPointF::x
qreal x() const const
QPointF::y
qreal y() const const
QRect
QRect::height
int height() const const
QRect::size
QSize size() const const
QRect::width
int width() const const
QSettings
QSize
QString
QString::toDouble
double toDouble(bool *ok) const const
QString::toInt
int toInt(bool *ok, int base) const const
Qt::red
red
QTransform
QTransform::rotate
QTransform & rotate(qreal angle, Qt::Axis axis)
QTransform::scale
QTransform & scale(qreal sx, qreal sy)
QTransform::translate
QTransform & translate(qreal dx, qreal dy)
Generated on Sun Sep 24 2023 19:39:34 for Pencil2D by doxygen 1.9.6 based on revision 1395c86cb17dafbb32de44cbabe1f4c58636468d