diff options
author | Florin Malita <fmalita@chromium.org> | 2018-01-29 10:49:49 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-01-29 16:16:21 +0000 |
commit | cca86f386cfd050cd03a25b305fc6fda48a8d6cd (patch) | |
tree | ed86f775c14946e84eefbb8cfe248c12ed7136ce /experimental | |
parent | a6717ce9fe02e1a251eaa39aa096dd90c6975f26 (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.cpp | 55 | ||||
-rw-r--r-- | experimental/skottie/SkottieAnimator.cpp | 8 | ||||
-rw-r--r-- | experimental/skottie/SkottieAnimator.h | 2 | ||||
-rw-r--r-- | experimental/sksg/SkSGScene.cpp | 9 | ||||
-rw-r--r-- | experimental/sksg/SkSGScene.h | 16 |
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(); |