aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2018-01-29 10:49:49 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-01-29 16:16:21 +0000
commitcca86f386cfd050cd03a25b305fc6fda48a8d6cd (patch)
treeed86f775c14946e84eefbb8cfe248c12ed7136ce /experimental
parenta6717ce9fe02e1a251eaa39aa096dd90c6975f26 (diff)
[skottie] Hierarchical animators
Instead of a flat animator space, introduce animator groups. This allows us to encapsulate layer animators and only dispatch ticks when their owning layer is active. TBR= Change-Id: I1fc8a55abf68a712b71969bb1a11275dbe54c236 Reviewed-on: https://skia-review.googlesource.com/101201 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'experimental')
-rw-r--r--experimental/skottie/Skottie.cpp55
-rw-r--r--experimental/skottie/SkottieAnimator.cpp8
-rw-r--r--experimental/skottie/SkottieAnimator.h2
-rw-r--r--experimental/sksg/SkSGScene.cpp9
-rw-r--r--experimental/sksg/SkSGScene.h16
5 files changed, 62 insertions, 28 deletions
diff --git a/experimental/skottie/Skottie.cpp b/experimental/skottie/Skottie.cpp
index 1ec461423d..66b84b5750 100644
--- a/experimental/skottie/Skottie.cpp
+++ b/experimental/skottie/Skottie.cpp
@@ -18,7 +18,6 @@
#include "SkOSPath.h"
#include "SkPaint.h"
#include "SkParse.h"
-#include "SkPath.h"
#include "SkPoint.h"
#include "SkSGColor.h"
#include "SkSGDraw.h"
@@ -53,9 +52,9 @@ namespace {
using AssetMap = SkTHashMap<SkString, const Json::Value*>;
struct AttachContext {
- const ResourceProvider& fResources;
- const AssetMap& fAssets;
- sksg::Scene::AnimatorList& fAnimators;
+ const ResourceProvider& fResources;
+ const AssetMap& fAssets;
+ sksg::AnimatorList& fAnimators;
};
bool LogFail(const Json::Value& json, const char* msg) {
@@ -921,58 +920,72 @@ sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer,
return nullptr;
}
+ sksg::AnimatorList layer_animators;
+ AttachContext local_ctx =
+ { layerCtx->fCtx->fResources, layerCtx->fCtx->fAssets, layer_animators};
+
// Layer content.
- auto layer = gLayerAttachers[type](jlayer, layerCtx->fCtx);
+ auto layer = gLayerAttachers[type](jlayer, &local_ctx);
// Optional layer mask.
- layer = AttachMask(jlayer["masksProperties"], layerCtx->fCtx, std::move(layer));
+ layer = AttachMask(jlayer["masksProperties"], &local_ctx, std::move(layer));
// Optional layer transform.
if (auto layerMatrix = layerCtx->AttachLayerMatrix(jlayer)) {
layer = sksg::Transform::Make(std::move(layer), std::move(layerMatrix));
}
// Optional layer opacity.
- layer = AttachOpacity(jlayer["ks"], layerCtx->fCtx, std::move(layer));
+ layer = AttachOpacity(jlayer["ks"], &local_ctx, std::move(layer));
- // TODO: we should also disable related/inactive animators.
- class Activator final : public sksg::Animator {
+ class Activator final : public sksg::GroupAnimator {
public:
- Activator(sk_sp<sksg::OpacityEffect> controlNode, float in, float out)
- : fControlNode(std::move(controlNode))
+ Activator(sksg::AnimatorList&& layer_animators,
+ sk_sp<sksg::OpacityEffect> controlNode, float in, float out)
+ : INHERITED(std::move(layer_animators))
+ , fControlNode(std::move(controlNode))
, fIn(in)
, fOut(out) {}
void onTick(float t) override {
+ const auto active = (t >= fIn && t <= fOut);
+
// Keep the layer fully transparent except for its [in..out] lifespan.
// (note: opacity == 0 disables rendering, while opacity == 1 is a noop)
- fControlNode->setOpacity(t >= fIn && t <= fOut ? 1 : 0);
+ fControlNode->setOpacity(active ? 1 : 0);
+
+ // Dispatch ticks only while active.
+ if (active)
+ this->INHERITED::onTick(t);
}
private:
const sk_sp<sksg::OpacityEffect> fControlNode;
const float fIn,
fOut;
+
+ using INHERITED = sksg::GroupAnimator;
};
- auto layerControl = sksg::OpacityEffect::Make(std::move(layer));
- const auto in = ParseDefault(jlayer["ip"], 0.0f),
- out = ParseDefault(jlayer["op"], in);
+ auto controller = sksg::OpacityEffect::Make(std::move(layer));
+ const auto in = ParseDefault(jlayer["ip"], 0.0f),
+ out = ParseDefault(jlayer["op"], in);
- if (in >= out || ! layerControl)
+ if (in >= out || !controller)
return nullptr;
- layerCtx->fCtx->fAnimators.push_back(skstd::make_unique<Activator>(layerControl, in, out));
+ layerCtx->fCtx->fAnimators.push_back(
+ skstd::make_unique<Activator>(std::move(layer_animators), controller, in, out));
if (ParseDefault(jlayer["td"], false)) {
// This layer is a matte. We apply it as a mask to the next layer.
- layerCtx->fCurrentMatte = std::move(layerControl);
+ layerCtx->fCurrentMatte = std::move(controller);
return nullptr;
}
if (layerCtx->fCurrentMatte) {
// There is a pending matte. Apply and reset.
- return sksg::MaskEffect::Make(std::move(layerControl), std::move(layerCtx->fCurrentMatte));
+ return sksg::MaskEffect::Make(std::move(controller), std::move(layerCtx->fCurrentMatte));
}
- return layerControl;
+ return controller;
}
sk_sp<sksg::RenderNode> AttachComposition(const Json::Value& comp, AttachContext* ctx) {
@@ -1091,7 +1104,7 @@ Animation::Animation(const ResourceProvider& resources,
assets.set(ParseDefault(asset["id"], SkString()), &asset);
}
- sksg::Scene::AnimatorList animators;
+ sksg::AnimatorList animators;
AttachContext ctx = { resources, assets, animators };
auto root = AttachComposition(json, &ctx);
diff --git a/experimental/skottie/SkottieAnimator.cpp b/experimental/skottie/SkottieAnimator.cpp
index b50e8ac442..c5cea588eb 100644
--- a/experimental/skottie/SkottieAnimator.cpp
+++ b/experimental/skottie/SkottieAnimator.cpp
@@ -275,7 +275,7 @@ private:
template <typename T>
static inline bool BindPropertyImpl(const Json::Value& jprop,
- sksg::Scene::AnimatorList* animators,
+ sksg::AnimatorList* animators,
std::function<void(const T&)>&& apply,
const T* noop) {
if (!jprop.isObject())
@@ -318,7 +318,7 @@ static inline bool BindPropertyImpl(const Json::Value& jprop,
template <>
bool BindProperty(const Json::Value& jprop,
- sksg::Scene::AnimatorList* animators,
+ sksg::AnimatorList* animators,
std::function<void(const ScalarValue&)>&& apply,
const ScalarValue* noop) {
return BindPropertyImpl(jprop, animators, std::move(apply), noop);
@@ -326,7 +326,7 @@ bool BindProperty(const Json::Value& jprop,
template <>
bool BindProperty(const Json::Value& jprop,
- sksg::Scene::AnimatorList* animators,
+ sksg::AnimatorList* animators,
std::function<void(const VectorValue&)>&& apply,
const VectorValue* noop) {
return BindPropertyImpl(jprop, animators, std::move(apply), noop);
@@ -334,7 +334,7 @@ bool BindProperty(const Json::Value& jprop,
template <>
bool BindProperty(const Json::Value& jprop,
- sksg::Scene::AnimatorList* animators,
+ sksg::AnimatorList* animators,
std::function<void(const ShapeValue&)>&& apply,
const ShapeValue* noop) {
return BindPropertyImpl(jprop, animators, std::move(apply), noop);
diff --git a/experimental/skottie/SkottieAnimator.h b/experimental/skottie/SkottieAnimator.h
index c32b4f8207..77be06b809 100644
--- a/experimental/skottie/SkottieAnimator.h
+++ b/experimental/skottie/SkottieAnimator.h
@@ -20,7 +20,7 @@ namespace skottie {
// it will either apply immediately or instantiate and attach a keyframe animator.
template <typename T>
bool BindProperty(const Json::Value&,
- sksg::Scene::AnimatorList*,
+ sksg::AnimatorList*,
std::function<void(const T&)>&&,
const T* noop = nullptr);
diff --git a/experimental/sksg/SkSGScene.cpp b/experimental/sksg/SkSGScene.cpp
index 85a1b43b1c..8d7e0b369b 100644
--- a/experimental/sksg/SkSGScene.cpp
+++ b/experimental/sksg/SkSGScene.cpp
@@ -22,6 +22,15 @@ void Animator::tick(float t) {
this->onTick(t);
}
+GroupAnimator::GroupAnimator(AnimatorList&& animators)
+ : fAnimators(std::move(animators)) {}
+
+void GroupAnimator::onTick(float t) {
+ for (const auto& a : fAnimators) {
+ a->tick(t);
+ }
+}
+
std::unique_ptr<Scene> Scene::Make(sk_sp<RenderNode> root, AnimatorList&& anims) {
return root ? std::unique_ptr<Scene>(new Scene(std::move(root), std::move(anims))) : nullptr;
}
diff --git a/experimental/sksg/SkSGScene.h b/experimental/sksg/SkSGScene.h
index 32186498d2..2081c1d747 100644
--- a/experimental/sksg/SkSGScene.h
+++ b/experimental/sksg/SkSGScene.h
@@ -39,6 +39,20 @@ private:
using INHERITED = SkNoncopyable;
};
+using AnimatorList = std::vector<std::unique_ptr<Animator>>;
+
+class GroupAnimator : public Animator {
+protected:
+ explicit GroupAnimator(AnimatorList&&);
+
+ void onTick(float t) override;
+
+private:
+ const AnimatorList fAnimators;
+
+ using INHERITED = Animator;
+};
+
/**
* Holds a scene root and a list of animators.
*
@@ -47,8 +61,6 @@ private:
*/
class Scene final : SkNoncopyable {
public:
- using AnimatorList = std::vector<std::unique_ptr<Animator>>;
-
static std::unique_ptr<Scene> Make(sk_sp<RenderNode> root, AnimatorList&& animators);
~Scene();