Skip to content

Commit

Permalink
Support interactive SVG
Browse files Browse the repository at this point in the history
Initial implementation, supports begin/end events on animated transforms.

Bumps evformat to 29.

Ref: #212
  • Loading branch information
rodlie committed Jul 23, 2024
1 parent 21f8114 commit 3b48e27
Show file tree
Hide file tree
Showing 12 changed files with 157 additions and 32 deletions.
9 changes: 8 additions & 1 deletion src/core/Animators/graphanimator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,10 @@ void GraphAnimator::graph_saveSVG(SvgExporter& exp,
const QString& attrName,
const ValueGetter& valueGetter,
const bool transform,
const QString& type) const {
const QString& type,
const QString &beginEvent,
const QString &endEvent) const
{
Q_ASSERT(!transform || attrName == "transform");
const auto relRange = prp_absRangeToRelRange(exp.fAbsRange);
const auto idRange = prp_getIdenticalRelRange(visRange.fMin);
Expand All @@ -543,6 +546,10 @@ void GraphAnimator::graph_saveSVG(SvgExporter& exp,
} else {
const auto tagName = transform ? "animateTransform" : "animate";
auto anim = exp.createElement(tagName);
if (transform) {
if (!beginEvent.isEmpty()) { anim.setAttribute("begin", beginEvent); }
if (!endEvent.isEmpty()) { anim.setAttribute("end", endEvent); }
}
anim.setAttribute("attributeName", attrName);
if(!type.isEmpty()) anim.setAttribute("type", type);
const qreal div = span - 1;
Expand Down
4 changes: 3 additions & 1 deletion src/core/Animators/graphanimator.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ class CORE_EXPORT GraphAnimator : public Animator {
const QString& attrName,
const ValueGetter& valueGetter,
const bool transform = false,
const QString& type = "") const;
const QString& type = "",
const QString& beginEvent = "",
const QString& endEvent = "") const;
protected:
qreal graph_prevKeyWeight(const GraphKey * const prevKey,
const GraphKey * const nextKey,
Expand Down
15 changes: 11 additions & 4 deletions src/core/Animators/qpointfanimator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,13 @@ void QPointFAnimator::saveQPointFSVGX(SvgExporter& exp,
const qreal y,
const qreal multiplier,
const bool transform,
const QString& type) const {
const QString& type,
const QString &beginEvent,
const QString &endEvent) const
{
const QString templ = "%1 " + QString::number(y);
mXAnimator->saveQrealSVG(exp, parent, visRange, name, multiplier,
transform, type, templ);
transform, type, templ, beginEvent, endEvent);
}

void QPointFAnimator::saveQPointFSVGY(SvgExporter& exp,
Expand All @@ -271,10 +274,14 @@ void QPointFAnimator::saveQPointFSVGY(SvgExporter& exp,
const qreal x,
const qreal multiplier,
const bool transform,
const QString& type) const {
const QString& type,
const QString &beginEvent,
const QString &endEvent) const
{
const QString templ = QString::number(x) + " %1";
mYAnimator->saveQrealSVG(exp, parent, visRange, name, multiplier,
transform, type, templ);
transform, type, templ,
beginEvent, endEvent);
}

QDomElement QPointFAnimator::prp_writePropertyXEV_impl(const XevExporter& exp) const {
Expand Down
8 changes: 6 additions & 2 deletions src/core/Animators/qpointfanimator.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,19 @@ class CORE_EXPORT QPointFAnimator : public StaticComplexAnimator {
const qreal y,
const qreal multiplier,
const bool transform = false,
const QString& type = "") const;
const QString& type = "",
const QString& beginEvent = "",
const QString& endEvent = "") const;
void saveQPointFSVGY(SvgExporter& exp,
QDomElement& parent,
const FrameRange& visRange,
const QString& name,
const qreal x,
const qreal multiplier,
const bool transform = false,
const QString& type = "") const;
const QString& type = "",
const QString& beginEvent = "",
const QString& endEvent = "") const;
QDomElement prp_writePropertyXEV_impl(const XevExporter& exp) const;
protected:
qsptr<QrealAnimator> mXAnimator;
Expand Down
16 changes: 11 additions & 5 deletions src/core/Animators/qrealanimator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -778,33 +778,39 @@ void QrealAnimator::saveQrealSVG(SvgExporter& exp,
const qreal multiplier,
const bool transform,
const QString& type,
const QString& templ) {
const QString& templ,
const QString &beginEvent,
const QString &endEvent)
{
const auto mangler = [multiplier](const qreal value) {
return value*multiplier;
};
saveQrealSVG(exp, parent, visRange, attrName,
mangler, transform, type, templ);
mangler, transform, type, templ, beginEvent, endEvent);
}

void QrealAnimator::saveQrealSVG(SvgExporter& exp, QDomElement& parent,
const FrameRange& visRange, const QString& attrName,
const Mangler& mangler, const bool transform,
const QString& type, const QString& templ) {
const QString& type, const QString& templ,
const QString &beginEvent, const QString &endEvent)
{
if(hasValidExpression()) {
const auto copy = enve::make_shared<QrealAnimator>("");
const auto relRange = prp_absRangeToRelRange(exp.fAbsRange);
copy->prp_setInheritedFrameShift(prp_getTotalFrameShift(), nullptr);
copy->setExpression(mExpression.sptr());
copy->applyExpression(relRange, 10, false);
copy->saveQrealSVG(exp, parent, visRange, attrName,
mangler, transform, type, templ);
mangler, transform, type, templ,
beginEvent, endEvent);
setExpression(mExpression.sptr());
} else {
graph_saveSVG(exp, parent, visRange, attrName,
[this, mangler, &templ](const int relFrame) {
const qreal val = mangler(getEffectiveValue(relFrame));
return templ.arg(val);
}, transform, type);
}, transform, type, beginEvent, endEvent);
}
}

Expand Down
8 changes: 6 additions & 2 deletions src/core/Animators/qrealanimator.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,9 @@ class CORE_EXPORT QrealAnimator : public GraphAnimator {
const qreal multiplier = 1.,
const bool transform = false,
const QString& type = "",
const QString& templ = "%1");
const QString& templ = "%1",
const QString& beginEvent = "",
const QString& endEvent = "");
using Mangler = std::function<qreal(qreal)>;
void saveQrealSVG(SvgExporter& exp,
QDomElement& parent,
Expand All @@ -188,7 +190,9 @@ class CORE_EXPORT QrealAnimator : public GraphAnimator {
const Mangler& mangler,
const bool transform = false,
const QString& type = "",
const QString& templ = "%1");
const QString& templ = "%1",
const QString& beginEvent = "",
const QString& endEvent = "");
private:
qreal calculateBaseValueAtRelFrame(const qreal frame) const;
void startBaseValueTransform();
Expand Down
10 changes: 8 additions & 2 deletions src/core/Animators/staticcomplexanimator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
// Fork of enve - Copyright (C) 2016-2020 Maurycy Liebner

#include "staticcomplexanimator.h"
#include "ReadWrite/evformat.h"

StaticComplexAnimator::StaticComplexAnimator(const QString &name) :
ComplexAnimator(name) {}
Expand All @@ -34,10 +35,15 @@ void StaticComplexAnimator::prp_writeProperty_impl(eWriteStream &dst) const {
prop->prp_writeProperty(dst);
}

void StaticComplexAnimator::prp_readProperty_impl(eReadStream &src) {
void StaticComplexAnimator::prp_readProperty_impl(eReadStream &src)
{
const auto& children = ca_getChildren();
for(const auto& prop : children)
const auto SVGProperties = QStringList() << "begin event" << "end event";
for (const auto& prop : children) {
if (src.evFileVersion() < EvFormat::svgBeginEnd &&
SVGProperties.contains(prop->prp_getName())) { continue; }
prop->prp_readProperty(src);
}
}

void StaticComplexAnimator::prp_readPropertyXEV_impl(
Expand Down
76 changes: 61 additions & 15 deletions src/core/Animators/transformanimator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ BasicTransformAnimator::BasicTransformAnimator() :
mRotAnimator = enve::make_shared<QrealAnimator>("rotation");
mRotAnimator->setCurrentBaseValue(0);

const auto events = QStringList() << "none" << "click" << "dblclick"
<< "mousedown" << "mouseenter" << "mouseleave"
<< "mousemove" << "mouseout" << "mouseover"
<< "mouseup";

mSVGBeginProperty = enve::make_shared<ComboBoxProperty>("begin event", events);
mSVGEndProperty = enve::make_shared<ComboBoxProperty>("end event", events);

ca_addChild(mSVGBeginProperty);
ca_addChild(mSVGEndProperty);
ca_addChild(mPosAnimator);
ca_addChild(mRotAnimator);
ca_addChild(mScaleAnimator);
Expand Down Expand Up @@ -588,13 +598,33 @@ BoxTransformAnimator::BoxTransformAnimator() {
getPointsHandler()->appendPt(pivotPt);
}

const QString BoxTransformAnimator::getSVGPropertyAction(const int value)
{
switch(value) {
case 1: return "click";
case 2: return "dblclick";
case 3: return "mousedown";
case 4: return "mouseenter";
case 5: return "mouseleave";
case 6: return "mousemove";
case 7: return "mouseout";
case 8: return "mouseover";
case 9: return "mouseup";
default:;
}
return QString();
}

QDomElement saveSVG_Split(QPointFAnimator* const anim,
const FrameRange& visRange,
const qreal multiplier,
const qreal def,
const QString& type,
SvgExporter& exp,
const QDomElement& child) {
const QDomElement& child,
const QString& beginEvent,
const QString& endEvent)
{
const auto animX = anim->getXAnimator();
const auto animY = anim->getYAnimator();

Expand All @@ -608,33 +638,43 @@ QDomElement saveSVG_Split(QPointFAnimator* const anim,
if(yStatic) {
const qreal y = multiplier*animY->getEffectiveValue();
anim->saveQPointFSVGX(exp, unpivot, visRange, "transform", y,
multiplier, true, type);
multiplier, true, type,
beginEvent, endEvent);
} else {
const qreal x = multiplier*animX->getEffectiveValue();
anim->saveQPointFSVGY(exp, unpivot, visRange, "transform", x,
multiplier, true, type);
multiplier, true, type,
beginEvent, endEvent);
}
unpivot.appendChild(child);
return unpivot;
} else {
auto xEle = exp.createElement("g");
anim->saveQPointFSVGX(exp, xEle, visRange, "transform", def,
multiplier, true, type);
multiplier, true, type,
beginEvent, endEvent);
auto yEle = exp.createElement("g");
anim->saveQPointFSVGY(exp, yEle, visRange, "transform", def,
multiplier, true, type);
multiplier, true, type,
beginEvent, endEvent);

yEle.appendChild(child);
xEle.appendChild(yEle);
return xEle;
}
}

QDomElement BoxTransformAnimator::saveSVG(
SvgExporter& exp, const FrameRange& visRange,
const QDomElement& child) const {
QDomElement BoxTransformAnimator::saveSVG(SvgExporter& exp,
const FrameRange& visRange,
const QDomElement& child) const
{

const auto beginEvent = getSVGPropertyAction(mSVGBeginProperty->getCurrentValue());
const auto endEvent = getSVGPropertyAction(mSVGEndProperty->getCurrentValue());

auto unpivot = saveSVG_Split(getPivotAnimator(), visRange, -1, 0,
"translate", exp, child);
"translate", exp, child,
beginEvent, endEvent);
{
const auto opaAnim = getOpacityAnimator();
opaAnim->saveQrealSVG(exp, unpivot, visRange, "opacity", 0.01);
Expand All @@ -646,24 +686,30 @@ QDomElement BoxTransformAnimator::saveSVG(
const auto shearXAnim = shearAnim->getXAnimator();
const auto shearYAnim = shearAnim->getYAnimator();
shearXAnim->saveQrealSVG(exp, shear, visRange,
"transform", 45, true, "skewX");
"transform", 45, true, "skewX", "%1",
beginEvent, endEvent);
shearYAnim->saveQrealSVG(exp, shear, visRange,
"transform", 45, true, "skewY");
"transform", 45, true, "skewY", "%1",
beginEvent, endEvent);
shear.appendChild(unpivot);
}
const auto scale = saveSVG_Split(getScaleAnimator(), visRange, 1, 1,
"scale", exp, shear);
"scale", exp, shear,
beginEvent, endEvent);

auto rotate = exp.createElement("g");
{
getRotAnimator()->saveQrealSVG(exp, rotate, visRange,
"transform", 1, true, "rotate");
"transform", 1, true, "rotate",
"%1", beginEvent, endEvent);
rotate.appendChild(scale);
}
const auto translate = saveSVG_Split(getPosAnimator(), visRange, 1, 0,
"translate", exp, rotate);
"translate", exp, rotate,
beginEvent, endEvent);
auto pivot = saveSVG_Split(getPivotAnimator(), visRange, 1, 0,
"translate", exp, translate);
"translate", exp, translate,
beginEvent, endEvent);

return pivot;
}
5 changes: 5 additions & 0 deletions src/core/Animators/transformanimator.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#ifndef TRANSFORMANIMATOR_H
#define TRANSFORMANIMATOR_H
#include "Properties/comboboxproperty.h"
#include "staticcomplexanimator.h"
#include "../skia/skiaincludes.h"
#include "transformvalues.h"
Expand Down Expand Up @@ -119,6 +120,9 @@ class CORE_EXPORT BasicTransformAnimator : public StaticComplexAnimator {
qsptr<QPointFAnimator> mPosAnimator;
qsptr<QPointFAnimator> mScaleAnimator;
qsptr<QrealAnimator> mRotAnimator;
qsptr<ComboBoxProperty> mSVGBeginProperty;
qsptr<ComboBoxProperty> mSVGEndProperty;

private:
bool rotationFlipped() const;
signals:
Expand Down Expand Up @@ -201,6 +205,7 @@ class CORE_EXPORT BoxTransformAnimator : public AdvancedTransformAnimator {
protected:
BoxTransformAnimator();
public:
static const QString getSVGPropertyAction(const int value);
QDomElement saveSVG(SvgExporter& exp, const FrameRange& visRange,
const QDomElement& child) const;
};
Expand Down
Loading

0 comments on commit 3b48e27

Please sign in to comment.