skia2/modules/skottie/utils/SkottieUtils.h
Florin Malita 3f45e4b322 [skottie] Custom prop manager updates
Currently we use a hard-coded name prefix ('$') and the properties are
"namespaced" (the tree hierarchy is part of the key name).

This doesn't work well for most clients looking to test property
manipulation, as they would rather handle similarly named props in
bulk.

E.g. instead of

  precomp1.layer1.Group1.COLOR_01
  precomp1.layer1.Group1.COLOR_02
  precomp1.layer2.Group1.COLOR_01
  precomp1.layer2.Group2.COLOR_02

the UI should simply present

  COLOR_01
  COLOR_02

To support this, introduce a new operation mode for
CustomPropertyManager (kCollapseProperties), and keep the old behavior
around as kNamespacedProperties.

Also drop filtering for markers as anyone interested in markers would
want to see all of them.

Plumb these options all the way into CK (to be added to the player
later).

Change-Id: I57ec78c669f3870939d48fbfc492b97f63ea600d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/312301
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Commit-Queue: Florin Malita <fmalita@google.com>
2020-08-20 19:59:22 +00:00

133 lines
4.5 KiB
C++

/*
* 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 SkottieUtils_DEFINED
#define SkottieUtils_DEFINED
#include "modules/skottie/include/ExternalLayer.h"
#include "modules/skottie/include/Skottie.h"
#include "modules/skottie/include/SkottieProperty.h"
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
namespace skottie_utils {
/**
* CustomPropertyManager implements a property management scheme where color/opacity/transform
* attributes are grouped and manipulated by name (one-to-many mapping).
*
* - setters apply the value to all properties in a named group
*
* - getters return all the managed property groups, and the first value within each of them
* (unchecked assumption: all properties within the same group have the same value)
*
* Attach to an Animation::Builder using the utility methods below to intercept properties and
* markers at build time.
*/
class CustomPropertyManager final {
public:
enum class Mode {
kCollapseProperties, // keys ignore the ancestor chain and are
// grouped based on the local node name
kNamespacedProperties, // keys include the ancestor node names (no grouping)
};
explicit CustomPropertyManager(Mode = Mode::kNamespacedProperties,
const char* prefix = nullptr);
~CustomPropertyManager();
using PropKey = std::string;
std::vector<PropKey> getColorProps() const;
skottie::ColorPropertyValue getColor(const PropKey&) const;
bool setColor(const PropKey&, const skottie::ColorPropertyValue&);
std::vector<PropKey> getOpacityProps() const;
skottie::OpacityPropertyValue getOpacity(const PropKey&) const;
bool setOpacity(const PropKey&, const skottie::OpacityPropertyValue&);
std::vector<PropKey> getTransformProps() const;
skottie::TransformPropertyValue getTransform(const PropKey&) const;
bool setTransform(const PropKey&, const skottie::TransformPropertyValue&);
std::vector<PropKey> getTextProps() const;
skottie::TextPropertyValue getText(const PropKey&) const;
bool setText(const PropKey&, const skottie::TextPropertyValue&);
struct MarkerInfo {
std::string name;
float t0, t1;
};
const std::vector<MarkerInfo>& markers() const { return fMarkers; }
// Returns a property observer to be attached to an animation builder.
sk_sp<skottie::PropertyObserver> getPropertyObserver() const;
// Returns a marker observer to be attached to an animation builder.
sk_sp<skottie::MarkerObserver> getMarkerObserver() const;
private:
class PropertyInterceptor;
class MarkerInterceptor;
std::string acceptKey(const char*, const char*) const;
template <typename T>
using PropGroup = std::vector<std::unique_ptr<T>>;
template <typename T>
using PropMap = std::unordered_map<PropKey, PropGroup<T>>;
template <typename T>
std::vector<PropKey> getProps(const PropMap<T>& container) const;
template <typename V, typename T>
V get(const PropKey&, const PropMap<T>& container) const;
template <typename V, typename T>
bool set(const PropKey&, const V&, const PropMap<T>& container);
const Mode fMode;
const SkString fPrefix;
sk_sp<PropertyInterceptor> fPropertyInterceptor;
sk_sp<MarkerInterceptor> fMarkerInterceptor;
PropMap<skottie::ColorPropertyHandle> fColorMap;
PropMap<skottie::OpacityPropertyHandle> fOpacityMap;
PropMap<skottie::TransformPropertyHandle> fTransformMap;
PropMap<skottie::TextPropertyHandle> fTextMap;
std::vector<MarkerInfo> fMarkers;
std::string fCurrentNode;
};
/**
* A sample PrecompInterceptor implementation.
*
* Attempts to substitute all precomp layers matching the given pattern (name prefix)
* with external Lottie animations.
*/
class ExternalAnimationPrecompInterceptor final : public skottie::PrecompInterceptor {
public:
ExternalAnimationPrecompInterceptor(sk_sp<skresources::ResourceProvider>, const char prefix[]);
~ExternalAnimationPrecompInterceptor() override;
private:
sk_sp<skottie::ExternalLayer> onLoadPrecomp(const char[], const char[], const SkSize&) override;
const sk_sp<skresources::ResourceProvider> fResourceProvider;
const SkString fPrefix;
};
} // namespace skottie_utils
#endif // SkottieUtils_DEFINED