17#include "layercamera.h"
20#include <QEasingCurve>
25LayerCamera::LayerCamera(
int id) :
Layer(id,
Layer::CAMERA)
27 setName(tr(
"Camera Layer"));
30 mFieldW = settings.value(
"FieldW").toInt();
31 mFieldH = settings.value(
"FieldH").toInt();
32 if (mFieldW < 2 || mFieldH < 2)
37 viewRect =
QRect(
QPoint(-mFieldW / 2, -mFieldH / 2),
QSize(mFieldW, mFieldH));
40LayerCamera::~LayerCamera()
48 splitControlPointIfNeeded(position);
53bool LayerCamera::removeKeyFrame(
int position)
55 mergeControlPointIfNeeded(position);
56 return Layer::removeKeyFrame(position);
59void LayerCamera::replaceKeyFrame(
const KeyFrame* camera)
61 *getCameraAtFrame(camera->pos()) = *
static_cast<const Camera*
>(camera);
64Camera* LayerCamera::getCameraAtFrame(
int frameNumber)
const
66 return static_cast<Camera*
>(getKeyFrameAt(frameNumber));
69Camera* LayerCamera::getLastCameraAtFrame(
int frameNumber,
int increment)
const
71 return static_cast<Camera*
>(getLastKeyFrameAtPosition(frameNumber + increment));
74QTransform LayerCamera::getViewAtFrame(
int frameNumber)
const
76 if (keyFrameCount() == 0)
82 if (frameNumber < firstKeyFramePosition())
84 frameNumber = firstKeyFramePosition();
87 Camera* camera1 =
static_cast<Camera*
>(getLastKeyFrameAtPosition(frameNumber));
89 int nextFrame = getNextKeyFramePosition(frameNumber);
90 Camera* camera2 =
static_cast<Camera*
>(getLastKeyFrameAtPosition(nextFrame));
92 if (camera1 ==
nullptr && camera2 ==
nullptr)
96 else if (camera1 ==
nullptr && camera2 !=
nullptr)
98 return camera2->getView();
100 else if (camera2 ==
nullptr && camera1 !=
nullptr)
102 return camera1->getView();
105 if (camera1->compare(*camera2))
107 return camera1->getView();
110 double frame1 = camera1->pos();
111 double frame2 = camera2->pos();
114 qreal percent = getInterpolationPercent(camera1->getEasingType(), (frameNumber - frame1) / (frame2 - frame1));
115 auto lerp = [](
double f1,
double f2,
double percent) ->
double
117 return f1 * (1.0 - percent) + f2 * percent;
120 QPointF controlPoint = camera1->getPathControlPoint();
121 if (!camera1->pathControlPointMoved()) {
122 controlPoint = getCenteredPathPoint(frame1);
125 const QPointF& point = getBezierPoint(camera1->translation(), camera2->translation(),
126 -controlPoint, percent);
128 double dx = point.
x();
129 double dy = point.
y();
130 double r = lerp(camera1->rotation(), camera2->rotation(), percent);
131 double s = lerp(camera1->scaling(), camera2->scaling(), percent);
134 camTransform.
scale(s, s);
141void LayerCamera::linearInterpolateTransform(
Camera* cam)
143 if (keyFrameCount() == 0)
146 int frameNumber = cam->pos();
147 Camera* camera1 =
static_cast<Camera*
>(getLastKeyFrameAtPosition(frameNumber - 1));
149 int nextFrame = getNextKeyFramePosition(frameNumber);
150 Camera* camera2 =
static_cast<Camera*
>(getLastKeyFrameAtPosition(nextFrame));
152 if (camera1 ==
nullptr && camera2 ==
nullptr)
157 else if (camera1 ==
nullptr && camera2 !=
nullptr)
159 return cam->assign(*camera2);
162 else if (camera2 ==
nullptr && camera1 !=
nullptr)
164 return cam->assign(*camera1);
167 if (camera1->compare(*camera2))
169 return cam->assign(*camera1);
172 double frame1 = camera1->pos();
173 double frame2 = camera2->pos();
176 qreal percent = getInterpolationPercent(camera1->getEasingType(), (frameNumber - frame1)/ (frame2 - frame1));
178 auto lerp = [](
double f1,
double f2,
double percent) ->
double
180 return f1 * (1.0 - percent) + f2 * percent;
183 QPointF controlPoint = camera1->getPathControlPoint();
184 if (!camera1->pathControlPointMoved()) {
185 controlPoint = getCenteredPathPoint(frame1);
188 QPointF point = getBezierPoint(camera1->translation(), camera2->translation(),
189 -controlPoint, percent);
190 double dx = point.
x();
191 double dy = point.
y();
192 double r = lerp(camera1->rotation(), camera2->rotation(), percent);
193 double s = lerp(camera1->scaling(), camera2->scaling(), percent);
195 cam->translate(dx, dy);
200qreal LayerCamera::getInterpolationPercent(CameraEasingType type, qreal percent)
const
247 default: Q_UNREACHABLE();
break;
254 QLineF line1(first, pathPoint);
255 QLineF line2(pathPoint, last);
256 return QLineF(line1.pointAt(percent), line2.pointAt(percent)).
pointAt(percent);
259void LayerCamera::splitControlPointIfNeeded(
int frame)
const
261 int next = getNextKeyFramePosition(frame);
262 int prev = getPreviousKeyFramePosition(frame);
265 if (frame > prev && (frame > 1) && frame < next)
267 Camera* camFrame = getLastCameraAtFrame(frame, 0);
268 Camera* camPrev = getCameraAtFrame(prev);
269 Camera* camNext = getCameraAtFrame(next);
270 Q_ASSERT(camPrev && camFrame && camNext);
272 if (camPrev->pathControlPointMoved()) {
273 qreal t =
static_cast<qreal
>(frame - prev) / (next - prev);
274 QPointF previousControlPoint = camPrev->getPathControlPoint();
277 QLineF interpolatedLineCN =
QLineF(previousControlPoint, -camNext->translation());
280 QLineF interpolatedLinePC =
QLineF(-camPrev->translation(), previousControlPoint);
282 camPrev->setPathControlPoint(interpolatedLinePC.
pointAt(t));
283 camFrame->setPathControlPoint(interpolatedLineCN.
pointAt(t));
284 camFrame->setPathControlPointMoved(
true);
287 Camera* camPrev = getCameraAtFrame(prev);
288 camPrev->setPathControlPointMoved(
false);
292void LayerCamera::mergeControlPointIfNeeded(
int frame)
const
294 int next = getNextKeyFramePosition(frame);
295 int prev = getPreviousKeyFramePosition(frame);
298 if (frame > prev && (frame > 1) && frame < next)
300 Camera* camPrev = getCameraAtFrame(prev);
301 Camera* camFrame = getLastCameraAtFrame(frame, 0);
302 Camera* camNext = getCameraAtFrame(next);
303 Q_ASSERT(camPrev && camFrame && camNext);
305 if (camPrev->pathControlPointMoved()) {
308 const QLineF& interpolatedLineCN =
QLineF(camFrame->getPathControlPoint(), -camNext->translation());
311 const QLineF& interpolatedLinePC =
QLineF(-camPrev->translation(), camPrev->getPathControlPoint());
314#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
315 auto intersection = interpolatedLinePC.
intersects(interpolatedLineCN, &mergedCPoint);
317 auto intersection = interpolatedLinePC.
intersect(interpolatedLineCN, &mergedCPoint);
321 QLineF(camFrame->getPathControlPoint(), mergedCPoint).
length() < mControlPointMergeThreshold)
323 camPrev->setPathControlPoint(mergedCPoint);
324 camPrev->setPathControlPointMoved(
true);
326 camPrev->setPathControlPointMoved(
false);
332QRect LayerCamera::getViewRect()
const
337QSize LayerCamera::getViewSize()
const
339 return viewRect.
size();
342void LayerCamera::setViewRect(
QRect newViewRect)
344 viewRect = newViewRect;
347void LayerCamera::setCameraEasingAtFrame(CameraEasingType type,
int frame)
const
349 Camera* camera = getLastCameraAtFrame(frame, 0);
350 camera->setEasingType(type);
351 camera->updateViewTransform();
354void LayerCamera::resetCameraAtFrame(CameraFieldOption type,
int frame)
const
356 int frameToModify = frame;
357 if (!keyExists(frame)) {
358 frameToModify = getPreviousKeyFramePosition(frame);
360 Camera* camera = getLastCameraAtFrame(frameToModify, 0);
364 case CameraFieldOption::RESET_FIELD:
365 camera->resetTransform();
367 case CameraFieldOption::RESET_TRANSLATION:
368 camera->translate(
QPoint(0,0));
370 case CameraFieldOption::RESET_SCALING:
373 case CameraFieldOption::RESET_ROTATION:
376 case CameraFieldOption::ALIGN_HORIZONTAL: {
377 qreal otherYCoord = camera->translation().
y();
378 Camera* nextCam = getCameraAtFrame(getNextKeyFramePosition(frameToModify));
379 nextCam->translate(nextCam->translation().
x(), otherYCoord);
380 camera->setPathControlPointMoved(
false);
383 case CameraFieldOption::ALIGN_VERTICAL: {
384 qreal otherXCoord = camera->translation().
x();
385 Camera* nextCam = getCameraAtFrame(getNextKeyFramePosition(frameToModify));
386 nextCam->translate(otherXCoord, nextCam->translation().
y());
387 camera->setPathControlPointMoved(
false);
390 case CameraFieldOption::HOLD_FRAME: {
392 if (getMaxKeyFramePosition() == camera->pos()) {
return; }
394 QPointF translation = camera->translation();
395 qreal rotation = camera->rotation();
396 qreal scaling = camera->scaling();
397 camera->setPathControlPointMoved(
false);
398 Camera* nextCamera = getLastCameraAtFrame(getNextKeyFramePosition(frame), 0);
399 nextCamera->translate(translation);
400 nextCamera->scale(scaling);
401 nextCamera->rotate(rotation);
402 nextCamera->setPathControlPointMoved(
false);
410 if (type != CameraFieldOption::RESET_SCALING && type != CameraFieldOption::RESET_ROTATION) {
411 setPathMovedAtFrame(frame - 1,
false);
414 camera->updateViewTransform();
417void LayerCamera::updateDotColor(DotColorType color)
421 case DotColorType::RED:
424 case DotColorType::GREEN:
427 case DotColorType::BLUE:
430 case DotColorType::BLACK:
433 case DotColorType::WHITE:
437 mDotColorType = color;
440QString LayerCamera::getInterpolationTextAtFrame(
int frame)
const
442 Camera* camera = getLastCameraAtFrame(frame, 0);
443 return getInterpolationText(camera->getEasingType());
446QPointF LayerCamera::getPathControlPointAtFrame(
int frame)
const
448 Camera* camera = getCameraAtFrame(getPreviousKeyFramePosition(frame));
451 return camera->getPathControlPoint();
454bool LayerCamera::hasSameTranslation(
int frame1,
int frame2)
const
456 Camera* camera1 = getCameraAtFrame(frame1);
457 Camera* camera2 = getCameraAtFrame(frame2);
459 if (camera1 ==
nullptr)
463 else if (camera2 ==
nullptr)
468 return camera1->translation() == camera2->translation();
471QList<QPointF> LayerCamera::getBezierPointsAtFrame(
int frame)
const
474 int prevFrame = getPreviousKeyFramePosition(frame);
475 int nextFrame = getNextKeyFramePosition(frame);
476 if (prevFrame < nextFrame)
478 Camera* prevCam = getCameraAtFrame(prevFrame);
479 Camera* nextCam = getCameraAtFrame(nextFrame);
481 if (prevCam->pathControlPointMoved()) {
491QPointF LayerCamera::getCenteredPathPoint(
int frame)
const
493 if (!keyExists(frame) || frame == getMaxKeyFramePosition())
494 frame = getPreviousKeyFramePosition(frame);
495 int nextFrame = getNextKeyFramePosition(frame);
496 Camera* cam1 = getCameraAtFrame(frame);
497 Camera* cam2 = getCameraAtFrame(nextFrame);
499 if (cam1 && cam2 ==
nullptr) {
500 return -cam1->translation();
501 }
else if (cam2 && cam1 ==
nullptr) {
502 return -cam2->translation();
503 }
else if (cam1 ==
nullptr && cam2 ==
nullptr) {
506 return QLineF(-cam1->translation(), -cam2->translation()).
pointAt(0.5);
509void LayerCamera::setPathMovedAtFrame(
int frame,
bool moved)
const
511 Camera* cam = getLastCameraAtFrame(frame, 0);
514 cam->setPathControlPointMoved(moved);
517void LayerCamera::updatePathControlPointAtFrame(
const QPointF& point,
int frame)
const
519 Camera* camera = getLastCameraAtFrame(frame, 0);
522 camera->setPathControlPoint(point);
523 camera->setPathControlPointMoved(
true);
526void LayerCamera::loadImageAtFrame(
int frameNumber, qreal dx, qreal dy, qreal rotate, qreal scale, CameraEasingType easing,
const QPointF& pathPoint,
bool pathMoved)
528 if (keyExists(frameNumber))
530 removeKeyFrame(frameNumber);
533 camera->setPos(frameNumber);
534 camera->setEasingType(easing);
536 camera->setPathControlPoint(pathPoint);
537 camera->setPathControlPointMoved(pathMoved);
547KeyFrame* LayerCamera::createKeyFrame(
int position)
551 c->setEasingType(CameraEasingType::LINEAR);
552 linearInterpolateTransform(c);
553 c->setPathControlPoint(c->translation());
567 if (mDotColorType != DotColorType::RED) {
568 layerElem.
setAttribute(
"pathColorType",
static_cast<int>(mDotColorType));
571 foreachKeyFrame([&](
KeyFrame* pKeyFrame)
582 if (camera->getEasingType() != CameraEasingType::LINEAR) {
583 keyTag.
setAttribute(
"easing",
static_cast<int>(camera->getEasingType()));
585 if (camera->pathControlPointMoved()) {
586 keyTag.
setAttribute(
"pathCPX", camera->getPathControlPoint().
x());
587 keyTag.
setAttribute(
"pathCPY", camera->getPathControlPoint().
y());
595void LayerCamera::loadDomElement(
const QDomElement& element,
QString dataDirPath, ProgressCallback progressStep)
597 Q_UNUSED(dataDirPath)
598 Q_UNUSED(progressStep)
600 this->loadBaseDomElement(element);
605 updateDotColor(
static_cast<DotColorType
>(element.
attribute(
"pathColorType").
toInt()));
606 viewRect =
QRect(-width / 2, -height / 2, width, height);
609 while (!imageTag.
isNull())
612 if (!imageElement.
isNull())
614 if (imageElement.
tagName() ==
"camera")
622 CameraEasingType easing =
static_cast<CameraEasingType
>(imageElement.
attribute(
"easing",
"0").
toInt());
626 bool pathMoved = pathX != 0 || pathY != 0;
628 loadImageAtFrame(frame, dx, dy, rotate, scale, easing,
QPointF(pathX, pathY), pathMoved);
bool addKeyFrame(int position, KeyFrame *pKeyFrame) override
Adds a keyframe at the given position, unless one already exists.
virtual bool addKeyFrame(int position, KeyFrame *pKeyFrame)
Adds a keyframe at the given position, unless one already exists.
QDomElement createElement(const QString &tagName)
QString attribute(const QString &name, const QString &defValue) const const
void setAttribute(const QString &name, const QString &value)
QString tagName() const const
QDomNode appendChild(const QDomNode &newChild)
QDomNode firstChild() const const
bool isNull() const const
QDomNode nextSibling() const const
QDomElement toElement() const const
void setType(QEasingCurve::Type type)
qreal valueForProgress(qreal progress) const const
QLineF::IntersectType intersect(const QLineF &line, QPointF *intersectionPoint) const const
QLineF::IntersectionType intersects(const QLineF &line, QPointF *intersectionPoint) const const
qreal length() const const
QPointF pointAt(qreal t) const const
void append(const T &value)
double toDouble(bool *ok) const const
int toInt(bool *ok, int base) const const