From 35efaa8fd7538f636dfd3593f172a961745a5cd8 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Mon, 22 Jan 2018 12:57:06 -0500 Subject: [sksg] Animator, Scene Relocate some reusable logic from Skottie TBR= Change-Id: I8764e666c9f1127ed895ee1d16cd66d052469ac5 Reviewed-on: https://skia-review.googlesource.com/98160 Reviewed-by: Florin Malita Commit-Queue: Florin Malita --- experimental/skottie/Skottie.cpp | 59 ++++++++++++--------------- experimental/skottie/Skottie.h | 21 ++++------ experimental/skottie/SkottieAnimator.h | 15 ++----- experimental/sksg/SkSGScene.cpp | 61 ++++++++++++++++++++++++++++ experimental/sksg/SkSGScene.h | 73 ++++++++++++++++++++++++++++++++++ 5 files changed, 170 insertions(+), 59 deletions(-) create mode 100644 experimental/sksg/SkSGScene.cpp create mode 100644 experimental/sksg/SkSGScene.h (limited to 'experimental') diff --git a/experimental/skottie/Skottie.cpp b/experimental/skottie/Skottie.cpp index 7a08cec9df..becf3bf470 100644 --- a/experimental/skottie/Skottie.cpp +++ b/experimental/skottie/Skottie.cpp @@ -31,6 +31,7 @@ #include "SkSGOpacityEffect.h" #include "SkSGPath.h" #include "SkSGRect.h" +#include "SkSGScene.h" #include "SkSGTransform.h" #include "SkSGTrimEffect.h" #include "SkStream.h" @@ -50,9 +51,9 @@ namespace { using AssetMap = SkTHashMap; struct AttachContext { - const ResourceProvider& fResources; - const AssetMap& fAssets; - SkTArray>& fAnimators; + const ResourceProvider& fResources; + const AssetMap& fAssets; + sksg::Scene::AnimatorList& fAnimators; }; bool LogFail(const Json::Value& json, const char* msg) { @@ -878,14 +879,14 @@ sk_sp AttachLayer(const Json::Value& jlayer, layer = AttachOpacity(jlayer["ks"], layerCtx->fCtx, std::move(layer)); // TODO: we should also disable related/inactive animators. - class Activator final : public AnimatorBase { + class Activator final : public sksg::Animator { public: Activator(sk_sp controlNode, float in, float out) : fControlNode(std::move(controlNode)) , fIn(in) , fOut(out) {} - void tick(float t) override { + void onTick(float t) override { // 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); @@ -1035,59 +1036,49 @@ Animation::Animation(const ResourceProvider& resources, assets.set(ParseString(asset["id"], ""), &asset); } - AttachContext ctx = { resources, assets, fAnimators }; - fDom = AttachComposition(json, &ctx); + sksg::Scene::AnimatorList animators; + AttachContext ctx = { resources, assets, animators }; + auto root = AttachComposition(json, &ctx); + + LOG("** Attached %d animators\n", animators.size()); + + fScene = sksg::Scene::Make(std::move(root), std::move(animators)); // In case the client calls render before the first tick. this->animationTick(0); - - LOG("** Attached %d animators\n", fAnimators.count()); } Animation::~Animation() = default; +void Animation::setShowInval(bool show) { + if (fScene) { + fScene->setShowInval(show); + } +} + void Animation::render(SkCanvas* canvas, const SkRect* dstR) const { - if (!fDom) + if (!fScene) return; - sksg::InvalidationController ic; - fDom->revalidate(&ic, SkMatrix::I()); - - // TODO: proper inval SkAutoCanvasRestore restore(canvas, true); const SkRect srcR = SkRect::MakeSize(this->size()); if (dstR) { canvas->concat(SkMatrix::MakeRectToRect(srcR, *dstR, SkMatrix::kCenter_ScaleToFit)); } canvas->clipRect(srcR); - fDom->render(canvas); - - if (!fShowInval) - return; - - SkPaint fill, stroke; - fill.setAntiAlias(true); - fill.setColor(0x40ff0000); - stroke.setAntiAlias(true); - stroke.setColor(0xffff0000); - stroke.setStyle(SkPaint::kStroke_Style); - - for (const auto& r : ic) { - canvas->drawRect(r, fill); - canvas->drawRect(r, stroke); - } + fScene->render(canvas); } void Animation::animationTick(SkMSec ms) { + if (!fScene) + return; + // 't' in the BM model really means 'frame #' auto t = static_cast(ms) * fFrameRate / 1000; t = fInPoint + std::fmod(t, fOutPoint - fInPoint); - // TODO: this can be optimized quite a bit with some sorting/state tracking. - for (const auto& a : fAnimators) { - a->tick(t); - } + fScene->animate(t); } } // namespace skottie diff --git a/experimental/skottie/Skottie.h b/experimental/skottie/Skottie.h index e13bd0ae98..d2486dc946 100644 --- a/experimental/skottie/Skottie.h +++ b/experimental/skottie/Skottie.h @@ -23,12 +23,10 @@ class SkStream; namespace Json { class Value; } -namespace sksg { class RenderNode; } +namespace sksg { class Scene; } namespace skottie { -class AnimatorBase; - class ResourceProvider : public SkNoncopyable { public: virtual ~ResourceProvider() = default; @@ -54,23 +52,20 @@ public: SkScalar inPoint() const { return fInPoint; } SkScalar outPoint() const { return fOutPoint; } - void setShowInval(bool show) { fShowInval = show; } + void setShowInval(bool show); private: Animation(const ResourceProvider&, SkString ver, const SkSize& size, SkScalar fps, const Json::Value&); - SkString fVersion; - SkSize fSize; - SkScalar fFrameRate, - fInPoint, - fOutPoint; - - sk_sp fDom; - SkTArray> fAnimators; + SkString fVersion; + SkSize fSize; + SkScalar fFrameRate, + fInPoint, + fOutPoint; - bool fShowInval = false; + std::unique_ptr fScene; typedef SkNoncopyable INHERITED; }; diff --git a/experimental/skottie/SkottieAnimator.h b/experimental/skottie/SkottieAnimator.h index 4e63e12833..4ab877ecaf 100644 --- a/experimental/skottie/SkottieAnimator.h +++ b/experimental/skottie/SkottieAnimator.h @@ -12,6 +12,7 @@ #include "SkMakeUnique.h" #include "SkottiePriv.h" #include "SkottieProperties.h" +#include "SkSGScene.h" #include "SkTypes.h" #include @@ -19,16 +20,6 @@ namespace skottie { -class AnimatorBase : public SkNoncopyable { -public: - virtual ~AnimatorBase() = default; - - virtual void tick(float) = 0; - -protected: - AnimatorBase() = default; -}; - class KeyframeIntervalBase : public SkNoncopyable { public: KeyframeIntervalBase() = default; @@ -112,7 +103,7 @@ std::vector> ParseFrames(const Json::Value& jframes) { // Binds an animated/keyframed property to a node attribute setter. template -class Animator : public AnimatorBase { +class Animator final : public sksg::Animator { public: using ApplyFuncT = void(*)(NodeT*, const ValT&); static std::unique_ptr Make(std::vector>&& frames, @@ -125,7 +116,7 @@ public: : nullptr; } - void tick(float t) override { + void onTick(float t) override { const auto& frame = this->findFrame(t); ValT val; diff --git a/experimental/sksg/SkSGScene.cpp b/experimental/sksg/SkSGScene.cpp new file mode 100644 index 0000000000..85a1b43b1c --- /dev/null +++ b/experimental/sksg/SkSGScene.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSGScene.h" + +#include "SkCanvas.h" +#include "SkMatrix.h" +#include "SkPaint.h" +#include "SkSGInvalidationController.h" +#include "SkSGRenderNode.h" + +namespace sksg { + +Animator::Animator() = default; +Animator::~Animator() = default; + +void Animator::tick(float t) { + this->onTick(t); +} + +std::unique_ptr Scene::Make(sk_sp root, AnimatorList&& anims) { + return root ? std::unique_ptr(new Scene(std::move(root), std::move(anims))) : nullptr; +} + +Scene::Scene(sk_sp root, AnimatorList&& animators) + : fRoot(std::move(root)) + , fAnimators(std::move(animators)) {} + +Scene::~Scene() = default; + +void Scene::render(SkCanvas* canvas) const { + InvalidationController ic; + fRoot->revalidate(&ic, SkMatrix::I()); + fRoot->render(canvas); + + if (fShowInval) { + SkPaint fill, stroke; + fill.setAntiAlias(true); + fill.setColor(0x40ff0000); + stroke.setAntiAlias(true); + stroke.setColor(0xffff0000); + stroke.setStyle(SkPaint::kStroke_Style); + + for (const auto& r : ic) { + canvas->drawRect(r, fill); + canvas->drawRect(r, stroke); + } + } +} + +void Scene::animate(float t) { + for (const auto& anim : fAnimators) { + anim->tick(t); + } +} + +} // namespace sksg diff --git a/experimental/sksg/SkSGScene.h b/experimental/sksg/SkSGScene.h new file mode 100644 index 0000000000..32186498d2 --- /dev/null +++ b/experimental/sksg/SkSGScene.h @@ -0,0 +1,73 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkSGScene_DEFINED +#define SkSGScene_DEFINED + +#include "SkRefCnt.h" +#include "SkTypes.h" + +#include +#include + +class SkCanvas; + +namespace sksg { + +class RenderNode; + +/** + * Base class for animators. + * + */ +class Animator : public SkNoncopyable { +public: + virtual ~Animator(); + + void tick(float t); + +protected: + Animator(); + + virtual void onTick(float t) = 0; + +private: + using INHERITED = SkNoncopyable; +}; + +/** + * Holds a scene root and a list of animators. + * + * Provides high-level mehods for driving rendering and animations. + * + */ +class Scene final : SkNoncopyable { +public: + using AnimatorList = std::vector>; + + static std::unique_ptr Make(sk_sp root, AnimatorList&& animators); + ~Scene(); + + void render(SkCanvas*) const; + void animate(float t); + + void setShowInval(bool show) { fShowInval = show; } + +private: + Scene(sk_sp root, AnimatorList&& animators); + + const sk_sp fRoot; + const AnimatorList fAnimators; + + bool fShowInval = false; + + using INHERITED = SkNoncopyable; +}; + +} // namespace sksg + +#endif // SkSGScene_DEFINED -- cgit v1.2.3