Compare commits

...

2 Commits

Author SHA1 Message Date
Maurycy Liebner
52714d7d00 Implement ParentEffect. 2021-03-05 16:04:00 +01:00
Maurycy Liebner
4c930bda2a Transform effects cleanup. 2021-03-05 13:02:54 +01:00
21 changed files with 439 additions and 368 deletions

View File

@ -159,19 +159,9 @@ SkPoint BasicTransformAnimator::mapFromParent(const SkPoint &parentRelPos) const
return toSkPoint(mapFromParent(toQPointF(parentRelPos)));
}
QMatrix BasicTransformAnimator::getCurrentTransform() const {
QMatrix matrix;
matrix.translate(mPosAnimator->getEffectiveXValue(),
mPosAnimator->getEffectiveYValue());
matrix.rotate(mRotAnimator->getEffectiveValue());
matrix.scale(mScaleAnimator->getEffectiveXValue(),
mScaleAnimator->getEffectiveYValue());
return matrix;
}
QMatrix BasicTransformAnimator::getRelativeTransformAtFrame(
const qreal relFrame) const {
const qreal relFrame, QMatrix* postTransform) const {
Q_UNUSED(postTransform)
QMatrix matrix;
matrix.translate(mPosAnimator->getEffectiveXValue(relFrame),
mPosAnimator->getEffectiveYValue(relFrame));
@ -183,10 +173,10 @@ QMatrix BasicTransformAnimator::getRelativeTransformAtFrame(
}
void BasicTransformAnimator::moveByAbs(const QPointF &absTrans) {
if(!mParentTransform) return;
const auto savedRelPos = mPosAnimator->getSavedValue();
const auto savedAbsPos = mParentTransform->mapRelPosToAbs(savedRelPos);
const auto relPos = mParentTransform->mapAbsPosToRel(savedAbsPos + absTrans);
const auto transform = mPostTransform*mInheritedTransform;
const auto savedAbsPos = transform.map(savedRelPos);
const auto relPos = transform.inverted().map(savedAbsPos + absTrans);
setRelativePos(relPos);
}
@ -207,7 +197,8 @@ void BasicTransformAnimator::rotateRelativeToSavedValue(const qreal rotRel,
}
void BasicTransformAnimator::updateRelativeTransform(const UpdateReason reason) {
mRelTransform = getCurrentTransform();
mRelTransform = getRelativeTransformAtFrame(anim_getCurrentRelFrame(),
&mPostTransform);
updateTotalTransform(reason);
}
@ -271,19 +262,6 @@ void BasicTransformAnimator::scaleRelativeToSavedValue(const qreal sx,
mPosAnimator->setBaseValue(QPointF(matrix.dx(), matrix.dy()));
}
QMatrix BasicTransformAnimator::getParentTotalTransformAtRelFrame(
const qreal relFrame) {
if(mParentTransform.data() == nullptr) {
return QMatrix();
} else {
const qreal absFrame = prp_relFrameToAbsFrameF(relFrame);
const qreal parentRelFrame =
mParentTransform->prp_absFrameToRelFrameF(absFrame);
return mParentTransform->
getTotalTransformAtFrame(parentRelFrame);
}
}
QPointFAnimator *BasicTransformAnimator::getPosAnimator() const {
return mPosAnimator.get();
}
@ -506,45 +484,14 @@ QMatrix valuesToMatrix(const qreal pivotX, const qreal pivotY,
return matrix;
}
QMatrix AdvancedTransformAnimator::getCurrentTransform() const {
qreal pivotX = mPivotAnimator->getEffectiveXValue();
qreal pivotY = mPivotAnimator->getEffectiveYValue();
qreal posX = mPosAnimator->getEffectiveXValue();
qreal posY = mPosAnimator->getEffectiveYValue();
qreal rot = mRotAnimator->getEffectiveValue();
qreal scaleX = mScaleAnimator->getEffectiveXValue();
qreal scaleY = mScaleAnimator->getEffectiveYValue();
qreal shearX = mShearAnimator->getEffectiveXValue();
qreal shearY = mShearAnimator->getEffectiveYValue();
applyTransformEffects(anim_getCurrentRelFrame(),
pivotX, pivotY,
posX, posY,
rot,
scaleX, scaleY,
shearX, shearY);
QMatrix matrix = valuesToMatrix(pivotX, pivotY,
posX, posY,
rot,
scaleX, scaleY,
shearX, shearY);
return matrix;
}
void AdvancedTransformAnimator::applyTransformEffects(
const qreal relFrame,
qreal& pivotX, qreal& pivotY,
qreal& posX, qreal& posY,
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY) const {
qreal& shearX, qreal& shearY,
QMatrix& postTransform) const {
const auto parent = getFirstAncestor<BoundingBox>();
if(!parent) return;
parent->applyTransformEffects(relFrame,
@ -552,7 +499,8 @@ void AdvancedTransformAnimator::applyTransformEffects(
posX, posY,
rot,
scaleX, scaleY,
shearX, shearY);
shearX, shearY,
postTransform);
}
void AdvancedTransformAnimator::setValues(const TransformValues &values) {
@ -578,12 +526,6 @@ QMatrix AdvancedTransformAnimator::getRotScaleShearTransform() {
qreal shearX = mShearAnimator->getEffectiveXValue();
qreal shearY = mShearAnimator->getEffectiveYValue();
applyTransformEffects(anim_getCurrentRelFrame(),
pivotX, pivotY,
posX, posY,
rot,
scaleX, scaleY,
shearX, shearY);
QMatrix matrix = valuesToMatrix(pivotX, pivotY,
posX, posY,
@ -594,7 +536,8 @@ QMatrix AdvancedTransformAnimator::getRotScaleShearTransform() {
return matrix;
}
QMatrix AdvancedTransformAnimator::getRelativeTransformAtFrame(const qreal relFrame) const {
QMatrix AdvancedTransformAnimator::getRelativeTransformAtFrame(
const qreal relFrame, QMatrix* postTransform) const {
qreal pivotX = mPivotAnimator->getEffectiveXValue(relFrame);
qreal pivotY = mPivotAnimator->getEffectiveYValue(relFrame);
@ -609,20 +552,24 @@ QMatrix AdvancedTransformAnimator::getRelativeTransformAtFrame(const qreal relFr
qreal shearX = mShearAnimator->getEffectiveXValue(relFrame);
qreal shearY = mShearAnimator->getEffectiveYValue(relFrame);
applyTransformEffects(anim_getCurrentRelFrame(),
QMatrix postTransformT;
applyTransformEffects(relFrame,
pivotX, pivotY,
posX, posY,
rot,
scaleX, scaleY,
shearX, shearY);
shearX, shearY,
postTransformT);
if(postTransform) *postTransform = postTransformT;
QMatrix matrix = valuesToMatrix(pivotX, pivotY,
posX, posY,
rot,
scaleX, scaleY,
shearX, shearY);
const auto matrix = valuesToMatrix(pivotX, pivotY,
posX, posY,
rot,
scaleX, scaleY,
shearX, shearY);
return matrix;
return matrix*postTransformT;
}
BoxTransformAnimator::BoxTransformAnimator() {

View File

@ -34,8 +34,8 @@ protected:
BasicTransformAnimator();
public:
virtual void reset();
virtual QMatrix getCurrentTransform() const;
virtual QMatrix getRelativeTransformAtFrame(const qreal relFrame) const;
virtual QMatrix getRelativeTransformAtFrame(
const qreal relFrame, QMatrix* postTransform = nullptr) const;
virtual QMatrix getInheritedTransformAtFrame(const qreal relFrame) const;
virtual QMatrix getTotalTransformAtFrame(const qreal relFrame) const;
@ -92,8 +92,6 @@ public:
void setParentTransformAnimator(BasicTransformAnimator *parent);
QMatrix getParentTotalTransformAtRelFrame(const qreal relFrame);
QPointFAnimator *getPosAnimator() const;
QPointFAnimator *getScaleAnimator() const;
QrealAnimator *getRotAnimator() const;
@ -103,6 +101,7 @@ protected:
QList<qsptr<BasicTransformAnimator>> mChildBoxes;
QMatrix mRelTransform;
QMatrix mPostTransform;
QMatrix mInheritedTransform;
QMatrix mTotalTransform;
@ -124,15 +123,16 @@ protected:
AdvancedTransformAnimator();
public:
void reset();
QMatrix getRelativeTransformAtFrame(const qreal relFrame) const;
QMatrix getCurrentTransform() const;
QMatrix getRelativeTransformAtFrame(
const qreal relFrame, QMatrix* postTransform = nullptr) const;
void applyTransformEffects(const qreal relFrame,
qreal& pivotX, qreal& pivotY,
qreal& posX, qreal& posY,
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY) const;
qreal& shearX, qreal& shearY,
QMatrix& postTransform) const;
void setValues(const TransformValues& values);

View File

@ -310,14 +310,15 @@ void BoundingBox::applyTransformEffects(
qreal& posX, qreal& posY,
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY) {
qreal& shearX, qreal& shearY,
QMatrix& postTransform) {
mTransformEffectCollection->applyEffects(relFrame,
pivotX, pivotY,
posX, posY,
rot,
scaleX, scaleY,
shearX, shearY,
this);
postTransform, this);
}
bool BoundingBox::hasTransformEffects() const {

View File

@ -413,7 +413,8 @@ public:
qreal& posX, qreal& posY,
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY);
qreal& shearX, qreal& shearY,
QMatrix& postTransform);
bool hasTransformEffects() const;

View File

@ -0,0 +1,57 @@
// enve - 2D animations software
// Copyright (C) 2016-2020 Maurycy Liebner
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "followobjecteffect.h"
#include "Boxes/boundingbox.h"
#include "Animators/transformanimator.h"
#include "Animators/qrealanimator.h"
FollowObjectEffect::FollowObjectEffect() :
FollowObjectEffectBase("follow object",
TransformEffectType::followObject) {}
void FollowObjectEffect::applyEffect(const qreal relFrame,
qreal& pivotX, qreal& pivotY,
qreal& posX, qreal& posY,
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY,
QMatrix& postTransform,
BoundingBox* const parent) {
Q_UNUSED(pivotX)
Q_UNUSED(pivotY)
Q_UNUSED(shearX)
Q_UNUSED(shearY)
Q_UNUSED(postTransform)
if(!isVisible()) return;
if(!parent) return;
const auto target = targetProperty()->getTarget();
if(!target) return;
const qreal absFrame = prp_relFrameToAbsFrameF(relFrame);
const qreal targetRelFrame = target->prp_absFrameToRelFrameF(absFrame);
const auto parentTransform = parent->getInheritedTransformAtFrame(relFrame);
const auto targetTransform = target->getTotalTransformAtFrame(targetRelFrame);
const auto transform = targetTransform*parentTransform.inverted();
applyEffectWithTransform(relFrame, pivotX, pivotY,
posX, posY, rot,
scaleX, scaleY, shearX, shearY,
parent, transform);
}

View File

@ -14,16 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef FOLLOWOBJECTTRANSFORMEFFECT_H
#define FOLLOWOBJECTTRANSFORMEFFECT_H
#ifndef FOLLOWOBJECTEFFECT_H
#define FOLLOWOBJECTEFFECT_H
#include "targettransformeffect.h"
#include "followobjecteffectbase.h"
#include "Animators/qpointfanimator.h"
class FollowObjectTransformEffect : public TargetTransformEffect {
class FollowObjectEffect : public FollowObjectEffectBase {
public:
FollowObjectTransformEffect();
FollowObjectEffect();
void applyEffect(const qreal relFrame,
qreal &pivotX, qreal &pivotY,
@ -31,16 +29,8 @@ public:
qreal &rot,
qreal &scaleX, qreal &scaleY,
qreal &shearX, qreal &shearY,
QMatrix& postTransform,
BoundingBox* const parent) override;
private:
void setRotScaleAfterTargetChange(
BoundingBox* const oldTarget,
BoundingBox* const newTarget) override;
qsptr<QPointFAnimator> mPosInfluence;
qsptr<QPointFAnimator> mScaleInfluence;
qsptr<QrealAnimator> mRotInfluence;
};
#endif // FOLLOWOBJECTTRANSFORMEFFECT_H
#endif // FOLLOWOBJECTEFFECT_H

View File

@ -14,15 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "followobjectrelativetransformeffect.h"
#include "followobjecteffectbase.h"
#include "Boxes/boundingbox.h"
#include "Animators/transformanimator.h"
#include "Animators/qrealanimator.h"
FollowObjectRelativeTransformEffect::FollowObjectRelativeTransformEffect() :
TargetTransformEffect("follow object relative",
TransformEffectType::followObjectRelative) {
FollowObjectEffectBase::FollowObjectEffectBase(
const QString& name, const TransformEffectType type) :
TargetTransformEffect(name, type) {
mPosInfluence = enve::make_shared<QPointFAnimator>(
QPointF{1., 1.}, QPointF{-10., -10.},
QPointF{10., 10.}, QPointF{0.01, 0.01},
@ -39,7 +39,55 @@ FollowObjectRelativeTransformEffect::FollowObjectRelativeTransformEffect() :
ca_addChild(mRotInfluence);
}
void FollowObjectRelativeTransformEffect::setRotScaleAfterTargetChange(
void FollowObjectEffectBase::applyEffectWithTransform(
const qreal relFrame,
qreal& pivotX, qreal& pivotY,
qreal& posX, qreal& posY, qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY,
BoundingBox* const parent,
const QMatrix& transform) {
Q_UNUSED(pivotX);
Q_UNUSED(pivotY);
Q_UNUSED(shearX);
Q_UNUSED(shearY);
if(!isVisible()) return;
if(!parent) return;
const auto target = targetProperty()->getTarget();
if(!target) return;
const auto targetTransformAnimator = target->getTransformAnimator();
const qreal absFrame = prp_relFrameToAbsFrameF(relFrame);
const qreal targetRelFrame = target->prp_absFrameToRelFrameF(absFrame);
const auto relPivot = target->getPivotRelPos(targetRelFrame);
const auto p1 = relPivot*transform;
const auto rotAnim = targetTransformAnimator->getRotAnimator();
const qreal targetRot = rotAnim->getEffectiveValue(targetRelFrame);
const auto scaleAnim = targetTransformAnimator->getScaleAnimator();
const qreal xScale = scaleAnim->getEffectiveXValue(targetRelFrame);
const qreal yScale = scaleAnim->getEffectiveYValue(targetRelFrame);
const qreal posXInfl = mPosInfluence->getEffectiveXValue(relFrame);
const qreal posYInfl = mPosInfluence->getEffectiveYValue(relFrame);
const qreal scaleXInfl = mScaleInfluence->getEffectiveXValue(relFrame);
const qreal scaleYInfl = mScaleInfluence->getEffectiveYValue(relFrame);
const qreal rotInfl = mRotInfluence->getEffectiveValue(relFrame);
posX += p1.x()*posXInfl;
posY += p1.y()*posYInfl;
scaleX *= 1 + (xScale - 1)*scaleXInfl;
scaleY *= 1 + (yScale - 1)*scaleYInfl;
rot += targetRot*rotInfl;
}
void FollowObjectEffectBase::setRotScaleAfterTargetChange(
BoundingBox* const oldTarget, BoundingBox* const newTarget) {
const auto parent = getFirstAncestor<BoundingBox>();
if(!parent) return;
@ -84,53 +132,3 @@ void FollowObjectRelativeTransformEffect::setRotScaleAfterTargetChange(
parent->startScaleTransform();
parent->scale(scaleX, scaleY);
}
void FollowObjectRelativeTransformEffect::applyEffect(
const qreal relFrame,
qreal& pivotX, qreal& pivotY,
qreal& posX, qreal& posY,
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY,
BoundingBox* const parent) {
Q_UNUSED(pivotX);
Q_UNUSED(pivotY);
Q_UNUSED(shearX);
Q_UNUSED(shearY);
if(!isVisible()) return;
if(!parent) return;
const auto target = targetProperty()->getTarget();
if(!target) return;
const auto targetTransformAnimator = target->getTransformAnimator();
const qreal absFrame = prp_relFrameToAbsFrameF(relFrame);
const qreal targetRelFrame = target->prp_absFrameToRelFrameF(absFrame);
const auto targetTransform = target->getTotalTransformAtFrame(targetRelFrame);
const auto relPivot = target->getPivotRelPos(targetRelFrame);
const auto p1 = relPivot*targetTransform;
const auto rotAnim = targetTransformAnimator->getRotAnimator();
const qreal targetRot = rotAnim->getEffectiveValue(targetRelFrame);
const auto scaleAnim = targetTransformAnimator->getScaleAnimator();
const qreal xScale = scaleAnim->getEffectiveXValue(targetRelFrame);
const qreal yScale = scaleAnim->getEffectiveYValue(targetRelFrame);
const qreal posXInfl = mPosInfluence->getEffectiveXValue(relFrame);
const qreal posYInfl = mPosInfluence->getEffectiveYValue(relFrame);
const qreal scaleXInfl = mScaleInfluence->getEffectiveXValue(relFrame);
const qreal scaleYInfl = mScaleInfluence->getEffectiveYValue(relFrame);
const qreal rotInfl = mRotInfluence->getEffectiveValue(relFrame);
posX += p1.x()*posXInfl;
posY += p1.y()*posYInfl;
scaleX *= 1 + (xScale - 1)*scaleXInfl;
scaleY *= 1 + (yScale - 1)*scaleYInfl;
rot += targetRot*rotInfl;
}

View File

@ -0,0 +1,49 @@
// enve - 2D animations software
// Copyright (C) 2016-2020 Maurycy Liebner
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef FOLLOWOBJECTEFFECTBASE_H
#define FOLLOWOBJECTEFFECTBASE_H
#include "targettransformeffect.h"
#include "Animators/qpointfanimator.h"
class FollowObjectEffectBase : public TargetTransformEffect {
public:
FollowObjectEffectBase(const QString& name,
const TransformEffectType type);
protected:
void applyEffectWithTransform(
const qreal relFrame,
qreal &pivotX, qreal &pivotY,
qreal &posX, qreal &posY,
qreal &rot,
qreal &scaleX, qreal &scaleY,
qreal &shearX, qreal &shearY,
BoundingBox* const parent,
const QMatrix& transform);
protected:
void setRotScaleAfterTargetChange(
BoundingBox* const oldTarget,
BoundingBox* const newTarget) override;
qsptr<QPointFAnimator> mPosInfluence;
qsptr<QPointFAnimator> mScaleInfluence;
qsptr<QrealAnimator> mRotInfluence;
};
#endif // FOLLOWOBJECTEFFECTBASE_H

View File

@ -0,0 +1,58 @@
// enve - 2D animations software
// Copyright (C) 2016-2020 Maurycy Liebner
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "followobjectrelativeeffect.h"
#include "Boxes/boundingbox.h"
#include "Animators/transformanimator.h"
#include "Animators/qrealanimator.h"
FollowObjectRelativeEffect::FollowObjectRelativeEffect() :
FollowObjectEffectBase("follow object relative",
TransformEffectType::followObjectRelative) {
}
void FollowObjectRelativeEffect::applyEffect(
const qreal relFrame,
qreal& pivotX, qreal& pivotY,
qreal& posX, qreal& posY,
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY,
QMatrix& postTransform,
BoundingBox* const parent) {
Q_UNUSED(pivotX)
Q_UNUSED(pivotY)
Q_UNUSED(shearX)
Q_UNUSED(shearY)
Q_UNUSED(postTransform)
if(!isVisible()) return;
if(!parent) return;
const auto target = targetProperty()->getTarget();
if(!target) return;
const qreal absFrame = prp_relFrameToAbsFrameF(relFrame);
const qreal targetRelFrame = target->prp_absFrameToRelFrameF(absFrame);
const auto targetTransform = target->getTotalTransformAtFrame(targetRelFrame);
applyEffectWithTransform(relFrame, pivotX, pivotY,
posX, posY, rot,
scaleX, scaleY, shearX, shearY,
parent, targetTransform);
}

View File

@ -14,16 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef FOLLOWOBJECTRELATIVETRANSFORMEFFECT_H
#define FOLLOWOBJECTRELATIVETRANSFORMEFFECT_H
#ifndef FOLLOWOBJECTRELATIVEEFFECT_H
#define FOLLOWOBJECTRELATIVEEFFECT_H
#include "targettransformeffect.h"
#include "followobjecteffectbase.h"
#include "Animators/qpointfanimator.h"
class FollowObjectRelativeTransformEffect : public TargetTransformEffect {
class FollowObjectRelativeEffect :
public FollowObjectEffectBase {
public:
FollowObjectRelativeTransformEffect();
FollowObjectRelativeEffect();
void applyEffect(const qreal relFrame,
qreal &pivotX, qreal &pivotY,
@ -31,16 +30,8 @@ public:
qreal &rot,
qreal &scaleX, qreal &scaleY,
qreal &shearX, qreal &shearY,
QMatrix& postTransform,
BoundingBox* const parent) override;
private:
void setRotScaleAfterTargetChange(
BoundingBox* const oldTarget,
BoundingBox* const newTarget) override;
qsptr<QPointFAnimator> mPosInfluence;
qsptr<QPointFAnimator> mScaleInfluence;
qsptr<QrealAnimator> mRotInfluence;
};
#endif // FOLLOWOBJECTRELATIVETRANSFORMEFFECT_H
#endif // FOLLOWOBJECTRELATIVEEFFECT_H

View File

@ -1,137 +0,0 @@
// enve - 2D animations software
// Copyright (C) 2016-2020 Maurycy Liebner
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "followobjecttransformeffect.h"
#include "Boxes/boundingbox.h"
#include "Animators/transformanimator.h"
#include "Animators/qrealanimator.h"
FollowObjectTransformEffect::FollowObjectTransformEffect() :
TargetTransformEffect("follow object", TransformEffectType::followObject) {
mPosInfluence = enve::make_shared<QPointFAnimator>(
QPointF{1., 1.}, QPointF{-10., -10.},
QPointF{10., 10.}, QPointF{0.01, 0.01},
"pos influence");
mScaleInfluence = enve::make_shared<QPointFAnimator>(
QPointF{1., 1.}, QPointF{-10., -10.},
QPointF{10., 10.}, QPointF{0.01, 0.01},
"scale influence");
mRotInfluence = enve::make_shared<QrealAnimator>(
1, -10, 10, 0.01, "rot influence");
ca_addChild(mPosInfluence);
ca_addChild(mScaleInfluence);
ca_addChild(mRotInfluence);
}
void FollowObjectTransformEffect::setRotScaleAfterTargetChange(
BoundingBox* const oldTarget, BoundingBox* const newTarget) {
const auto parent = getFirstAncestor<BoundingBox>();
if(!parent) return;
const qreal scaleXInfl = mScaleInfluence->getEffectiveXValue();
const qreal scaleYInfl = mScaleInfluence->getEffectiveYValue();
const qreal rotInfl = mRotInfluence->getEffectiveValue();
qreal rot = 0.;
qreal scaleX = 1.;
qreal scaleY = 1.;
if(oldTarget) {
const auto trans = oldTarget->getTransformAnimator();
const auto rotAnim = trans->getRotAnimator();
const auto scaleAnim = trans->getScaleAnimator();
rot += rotAnim->getEffectiveValue()*rotInfl;
scaleX *= 1 + (scaleAnim->getEffectiveXValue() - 1)*scaleXInfl;
scaleY *= 1 + (scaleAnim->getEffectiveYValue() - 1)*scaleYInfl;
}
if(newTarget) {
const auto trans = newTarget->getTransformAnimator();
const auto rotAnim = trans->getRotAnimator();
const auto scaleAnim = trans->getScaleAnimator();
rot -= rotAnim->getEffectiveValue()*rotInfl;
const qreal scaleXDiv = 1 + (scaleAnim->getEffectiveXValue() - 1)*scaleXInfl;
const qreal scaleYDiv = 1 + (scaleAnim->getEffectiveYValue() - 1)*scaleYInfl;
if(!isZero4Dec(scaleXDiv)) {
scaleX /= scaleXDiv;
}
if(!isZero4Dec(scaleYDiv)) {
scaleY /= scaleYDiv;
}
}
parent->startRotTransform();
parent->rotateBy(rot);
parent->startScaleTransform();
parent->scale(scaleX, scaleY);
}
void FollowObjectTransformEffect::applyEffect(
const qreal relFrame,
qreal& pivotX, qreal& pivotY,
qreal& posX, qreal& posY,
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY,
BoundingBox* const parent) {
Q_UNUSED(pivotX);
Q_UNUSED(pivotY);
Q_UNUSED(shearX);
Q_UNUSED(shearY);
if(!isVisible()) return;
if(!parent) return;
const auto target = targetProperty()->getTarget();
if(!target) return;
const auto targetTransformAnimator = target->getTransformAnimator();
const qreal absFrame = prp_relFrameToAbsFrameF(relFrame);
const qreal targetRelFrame = target->prp_absFrameToRelFrameF(absFrame);
const auto parentTransform = parent->getInheritedTransformAtFrame(relFrame);
const auto targetTransform = target->getTotalTransformAtFrame(targetRelFrame);
const auto transform = targetTransform*parentTransform.inverted();
const auto relPivot = target->getPivotRelPos(targetRelFrame);
const auto p1 = relPivot*transform;
const auto rotAnim = targetTransformAnimator->getRotAnimator();
const qreal targetRot = rotAnim->getEffectiveValue(targetRelFrame);
const auto scaleAnim = targetTransformAnimator->getScaleAnimator();
const qreal xScale = scaleAnim->getEffectiveXValue(targetRelFrame);
const qreal yScale = scaleAnim->getEffectiveYValue(targetRelFrame);
const qreal posXInfl = mPosInfluence->getEffectiveXValue(relFrame);
const qreal posYInfl = mPosInfluence->getEffectiveYValue(relFrame);
const qreal scaleXInfl = mScaleInfluence->getEffectiveXValue(relFrame);
const qreal scaleYInfl = mScaleInfluence->getEffectiveYValue(relFrame);
const qreal rotInfl = mRotInfluence->getEffectiveValue(relFrame);
posX += p1.x()*posXInfl;
posY += p1.y()*posYInfl;
scaleX *= 1 + (xScale - 1)*scaleXInfl;
scaleY *= 1 + (yScale - 1)*scaleYInfl;
rot += targetRot*rotInfl;
}

View File

@ -14,13 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "followpathtransformeffect.h"
#include "followpatheffect.h"
#include "Boxes/pathbox.h"
#include "Animators/qrealanimator.h"
#include "Animators/transformanimator.h"
FollowPathTransformEffect::FollowPathTransformEffect() :
FollowPathEffect::FollowPathEffect() :
TargetTransformEffect("follow path", TransformEffectType::followPath) {
targetProperty()->setValidator<PathBox>();
@ -74,7 +74,7 @@ void calculateFollowRotPosChange(
posYChange = p1.y();
}
void FollowPathTransformEffect::setRotScaleAfterTargetChange(
void FollowPathEffect::setRotScaleAfterTargetChange(
BoundingBox* const oldTarget, BoundingBox* const newTarget) {
const bool rotate = mRotate->getValue();
if(!rotate) return;
@ -124,20 +124,21 @@ void FollowPathTransformEffect::setRotScaleAfterTargetChange(
parent->rotateBy(rot);
}
void FollowPathTransformEffect::applyEffect(
const qreal relFrame,
void FollowPathEffect::applyEffect(const qreal relFrame,
qreal& pivotX, qreal& pivotY,
qreal& posX, qreal& posY,
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY,
QMatrix& postTransform,
BoundingBox* const parent) {
Q_UNUSED(pivotX);
Q_UNUSED(pivotY);
Q_UNUSED(scaleX);
Q_UNUSED(scaleY);
Q_UNUSED(shearX);
Q_UNUSED(shearY);
Q_UNUSED(pivotX)
Q_UNUSED(pivotY)
Q_UNUSED(scaleX)
Q_UNUSED(scaleY)
Q_UNUSED(shearX)
Q_UNUSED(shearY)
Q_UNUSED(postTransform)
if(!isVisible()) return;

View File

@ -14,16 +14,16 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef FOLLOWPATHTRANSFORMEFFECT_H
#define FOLLOWPATHTRANSFORMEFFECT_H
#ifndef FOLLOWPATHEFFECT_H
#define FOLLOWPATHEFFECT_H
#include "targettransformeffect.h"
#include "Properties/boolproperty.h"
class FollowPathTransformEffect : public TargetTransformEffect {
class FollowPathEffect : public TargetTransformEffect {
public:
FollowPathTransformEffect();
FollowPathEffect();
void applyEffect(const qreal relFrame,
qreal &pivotX, qreal &pivotY,
@ -31,6 +31,7 @@ public:
qreal &rot,
qreal &scaleX, qreal &scaleY,
qreal &shearX, qreal &shearY,
QMatrix& postTransform,
BoundingBox* const parent) override;
private:
void setRotScaleAfterTargetChange(
@ -44,4 +45,4 @@ private:
};
#endif // FOLLOWPATHTRANSFORMEFFECT_H
#endif // FOLLOWPATHEFFECT_H

View File

@ -0,0 +1,55 @@
// enve - 2D animations software
// Copyright (C) 2016-2020 Maurycy Liebner
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "parenteffect.h"
#include "Boxes/boundingbox.h"
#include "Animators/transformanimator.h"
#include "Animators/qrealanimator.h"
ParentEffect::ParentEffect() :
FollowObjectEffectBase("parent", TransformEffectType::parent) {}
void ParentEffect::applyEffect(
const qreal relFrame,
qreal& pivotX, qreal& pivotY,
qreal& posX, qreal& posY,
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY,
QMatrix& postTransform,
BoundingBox* const parent) {
Q_UNUSED(pivotX)
Q_UNUSED(pivotY)
Q_UNUSED(posX)
Q_UNUSED(posY)
Q_UNUSED(rot)
Q_UNUSED(scaleX)
Q_UNUSED(scaleY)
Q_UNUSED(shearX)
Q_UNUSED(shearY)
if(!isVisible()) return;
if(!parent) return;
const auto target = targetProperty()->getTarget();
if(!target) return;
const qreal absFrame = prp_relFrameToAbsFrameF(relFrame);
const qreal targetRelFrame = target->prp_absFrameToRelFrameF(absFrame);
const auto targetTransAnim = target->getTransformAnimator();
postTransform = targetTransAnim->getRelativeTransformAtFrame(targetRelFrame);
}

View File

@ -0,0 +1,36 @@
// enve - 2D animations software
// Copyright (C) 2016-2020 Maurycy Liebner
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef PARENTEFFECT_H
#define PARENTEFFECT_H
#include "followobjecteffectbase.h"
class ParentEffect : public FollowObjectEffectBase {
public:
ParentEffect();
void applyEffect(const qreal relFrame,
qreal &pivotX, qreal &pivotY,
qreal &posX, qreal &posY,
qreal &rot,
qreal &scaleX, qreal &scaleY,
qreal &shearX, qreal &shearY,
QMatrix& postTransform,
BoundingBox* const parent) override;
};
#endif // PARENTEFFECT_H

View File

@ -14,13 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "tracktransformeffect.h"
#include "trackeffect.h"
#include "Boxes/boundingbox.h"
#include "Animators/qrealanimator.h"
#include "Animators/transformanimator.h"
TrackTransformEffect::TrackTransformEffect() :
TrackEffect::TrackEffect() :
TargetTransformEffect("track", TransformEffectType::track) {
mInfluence = enve::make_shared<QrealAnimator>(1, -1, 1, 0.01, "influence");
@ -36,7 +36,7 @@ qreal calculateTrackAngle(const QPointF& parentPos,
return trackAngle;
}
void TrackTransformEffect::setRotScaleAfterTargetChange(
void TrackEffect::setRotScaleAfterTargetChange(
BoundingBox* const oldTarget, BoundingBox* const newTarget) {
const auto parent = getFirstAncestor<BoundingBox>();
if(!parent) return;
@ -64,22 +64,24 @@ void TrackTransformEffect::setRotScaleAfterTargetChange(
parent->rotateBy(rot);
}
void TrackTransformEffect::applyEffect(
void TrackEffect::applyEffect(
const qreal relFrame,
qreal& pivotX, qreal& pivotY,
qreal& posX, qreal& posY,
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY,
QMatrix& postTransform,
BoundingBox* const parent) {
Q_UNUSED(pivotX);
Q_UNUSED(pivotY);
Q_UNUSED(posX);
Q_UNUSED(posY);
Q_UNUSED(scaleX);
Q_UNUSED(scaleY);
Q_UNUSED(shearX);
Q_UNUSED(shearY);
Q_UNUSED(pivotX)
Q_UNUSED(pivotY)
Q_UNUSED(posX)
Q_UNUSED(posY)
Q_UNUSED(scaleX)
Q_UNUSED(scaleY)
Q_UNUSED(shearX)
Q_UNUSED(shearY)
Q_UNUSED(postTransform)
if(!isVisible()) return;

View File

@ -14,14 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef TRACKTRANSFORMEFFECT_H
#define TRACKTRANSFORMEFFECT_H
#ifndef TRACKEFFECT_H
#define TRACKEFFECT_H
#include "targettransformeffect.h"
class TrackTransformEffect : public TargetTransformEffect {
class TrackEffect : public TargetTransformEffect {
public:
TrackTransformEffect();
TrackEffect();
void applyEffect(const qreal relFrame,
qreal &pivotX, qreal &pivotY,
@ -29,6 +29,7 @@ public:
qreal &rot,
qreal &scaleX, qreal &scaleY,
qreal &shearX, qreal &shearY,
QMatrix& postTransform,
BoundingBox* const parent) override;
private:
void setRotScaleAfterTargetChange(
@ -38,4 +39,4 @@ private:
qsptr<QrealAnimator> mInfluence;
};
#endif // TRACKTRANSFORMEFFECT_H
#endif // TRACKEFFECT_H

View File

@ -20,7 +20,9 @@
#include "Animators/eeffect.h"
enum class TransformEffectType {
track, followPath, followObject, followObjectRelative
track, followPath,
followObject, followObjectRelative,
parent
};
class TransformEffect : public eEffect {
@ -36,6 +38,7 @@ public:
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY,
QMatrix& postTransform,
BoundingBox* const parent) = 0;
void prp_setupTreeViewMenu(PropertyMenu * const menu);

View File

@ -17,10 +17,11 @@
#include "transformeffectcollection.h"
#include "ReadWrite/evformat.h"
#include "tracktransformeffect.h"
#include "followpathtransformeffect.h"
#include "followobjecttransformeffect.h"
#include "followobjectrelativetransformeffect.h"
#include "trackeffect.h"
#include "followpatheffect.h"
#include "followobjecteffect.h"
#include "followobjectrelativeeffect.h"
#include "parenteffect.h"
TransformEffectCollection::TransformEffectCollection() :
TransformEffectCollectionBase("transform effects") {}
@ -31,31 +32,38 @@ void TransformEffectCollection::prp_setupTreeViewMenu(PropertyMenu * const menu)
{
const PropertyMenu::PlainSelectedOp<TransformEffectCollection> aOp =
[](TransformEffectCollection * coll) {
coll->addChild(enve::make_shared<TrackTransformEffect>());
coll->addChild(enve::make_shared<TrackEffect>());
};
menu->addPlainAction("Add Track Effect", aOp);
}
{
const PropertyMenu::PlainSelectedOp<TransformEffectCollection> aOp =
[](TransformEffectCollection * coll) {
coll->addChild(enve::make_shared<FollowPathTransformEffect>());
coll->addChild(enve::make_shared<FollowPathEffect>());
};
menu->addPlainAction("Add Follow Path Effect", aOp);
}
{
const PropertyMenu::PlainSelectedOp<TransformEffectCollection> aOp =
[](TransformEffectCollection * coll) {
coll->addChild(enve::make_shared<FollowObjectTransformEffect>());
coll->addChild(enve::make_shared<FollowObjectEffect>());
};
menu->addPlainAction("Add Follow Object Effect", aOp);
}
{
const PropertyMenu::PlainSelectedOp<TransformEffectCollection> aOp =
[](TransformEffectCollection * coll) {
coll->addChild(enve::make_shared<FollowObjectRelativeTransformEffect>());
coll->addChild(enve::make_shared<FollowObjectRelativeEffect>());
};
menu->addPlainAction("Add Follow Object Relative Effect", aOp);
}
{
const PropertyMenu::PlainSelectedOp<TransformEffectCollection> aOp =
[](TransformEffectCollection * coll) {
coll->addChild(enve::make_shared<ParentEffect>());
};
menu->addPlainAction("Add Parent Effect", aOp);
}
menu->addSeparator();
TransformEffectCollection::prp_setupTreeViewMenu(menu);
}
@ -81,6 +89,7 @@ void TransformEffectCollection::applyEffects(
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY,
QMatrix& postTransform,
BoundingBox* const parent) const {
const int iMax = ca_getNumberOfChildren();
for(int i = 0; i < iMax; i++) {
@ -92,6 +101,7 @@ void TransformEffectCollection::applyEffects(
rot,
scaleX, scaleY,
shearX, shearY,
postTransform,
parent);
}
}
@ -100,13 +110,15 @@ qsptr<TransformEffect> createTransformEffectForType(
const TransformEffectType type) {
switch(type) {
case(TransformEffectType::track):
return enve::make_shared<TrackTransformEffect>();
return enve::make_shared<TrackEffect>();
case(TransformEffectType::followPath):
return enve::make_shared<FollowPathTransformEffect>();
return enve::make_shared<FollowPathEffect>();
case(TransformEffectType::followObject):
return enve::make_shared<FollowObjectTransformEffect>();
return enve::make_shared<FollowObjectEffect>();
case(TransformEffectType::followObjectRelative):
return enve::make_shared<FollowObjectRelativeTransformEffect>();
return enve::make_shared<FollowObjectRelativeEffect>();
case(TransformEffectType::parent):
return enve::make_shared<ParentEffect>();
default: RuntimeThrow("Invalid transform effect type '" +
QString::number(int(type)) + "'");
}

View File

@ -58,6 +58,7 @@ public:
qreal& rot,
qreal& scaleX, qreal& scaleY,
qreal& shearX, qreal& shearY,
QMatrix& postTransform,
BoundingBox* const parent) const;
};

View File

@ -244,11 +244,13 @@ SOURCES += \
Timeline/animationrect.cpp \
Timeline/durationrectangle.cpp \
Timeline/fixedlenanimationrect.cpp \
TransformEffects/followobjectrelativetransformeffect.cpp \
TransformEffects/followobjecttransformeffect.cpp \
TransformEffects/followpathtransformeffect.cpp \
TransformEffects/followobjecteffect.cpp \
TransformEffects/followobjecteffectbase.cpp \
TransformEffects/followobjectrelativeeffect.cpp \
TransformEffects/followpatheffect.cpp \
TransformEffects/parenteffect.cpp \
TransformEffects/targettransformeffect.cpp \
TransformEffects/tracktransformeffect.cpp \
TransformEffects/trackeffect.cpp \
TransformEffects/transformeffect.cpp \
TransformEffects/transformeffectcollection.cpp \
XML/xevexporter.cpp \
@ -584,11 +586,13 @@ HEADERS += \
Timeline/animationrect.h \
Timeline/durationrectangle.h \
Timeline/fixedlenanimationrect.h \
TransformEffects/followobjectrelativetransformeffect.h \
TransformEffects/followobjecttransformeffect.h \
TransformEffects/followpathtransformeffect.h \
TransformEffects/followobjecteffect.h \
TransformEffects/followobjecteffectbase.h \
TransformEffects/followobjectrelativeeffect.h \
TransformEffects/followpatheffect.h \
TransformEffects/parenteffect.h \
TransformEffects/targettransformeffect.h \
TransformEffects/tracktransformeffect.h \
TransformEffects/trackeffect.h \
TransformEffects/transformeffect.h \
TransformEffects/transformeffectcollection.h \
XML/runtimewriteid.h \