[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 <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/experimental/skottie/Skottie.cpp b/experimental/skottie/Skottie.cpp
index 7a08cec..becf3bf 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 @@
 using AssetMap = SkTHashMap<SkString, const Json::Value*>;
 
 struct AttachContext {
-    const ResourceProvider&                  fResources;
-    const AssetMap&                          fAssets;
-    SkTArray<std::unique_ptr<AnimatorBase>>& fAnimators;
+    const ResourceProvider&    fResources;
+    const AssetMap&            fAssets;
+    sksg::Scene::AnimatorList& fAnimators;
 };
 
 bool LogFail(const Json::Value& json, const char* msg) {
@@ -878,14 +879,14 @@
     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<sksg::OpacityEffect> 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 @@
         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<float>(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