[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>
This commit is contained in:
parent
d279cee2f2
commit
3f45e4b322
@ -4,12 +4,18 @@
|
||||
// assets is a dictionary of named blobs: { key: ArrayBuffer, ... }
|
||||
// The keys should be well-behaved strings - they're turned into null-terminated
|
||||
// strings for the native side.
|
||||
CanvasKit.MakeManagedAnimation = function(json, assets) {
|
||||
|
||||
// prop_filter_prefix is an optional string acting as a name filter for selecting
|
||||
// "interesting" Lottie properties (surfaced in the embedded player controls)
|
||||
CanvasKit.MakeManagedAnimation = function(json, assets, prop_filter_prefix) {
|
||||
if (!CanvasKit._MakeManagedAnimation) {
|
||||
throw 'Not compiled with MakeManagedAnimation';
|
||||
}
|
||||
if (!prop_filter_prefix) {
|
||||
prop_filter_prefix = '';
|
||||
}
|
||||
if (!assets) {
|
||||
return CanvasKit._MakeManagedAnimation(json, 0, nullptr, nullptr, nullptr);
|
||||
return CanvasKit._MakeManagedAnimation(json, 0, nullptr, nullptr, nullptr, prop_filter_prefix);
|
||||
}
|
||||
var assetNamePtrs = [];
|
||||
var assetDataPtrs = [];
|
||||
@ -43,7 +49,7 @@ CanvasKit.MakeManagedAnimation = function(json, assets) {
|
||||
var assetSizesPtr = copy1dArray(assetSizes, "HEAPU32");
|
||||
|
||||
var anim = CanvasKit._MakeManagedAnimation(json, assetKeys.length, namesPtr,
|
||||
assetsPtr, assetSizesPtr);
|
||||
assetsPtr, assetSizesPtr, prop_filter_prefix);
|
||||
|
||||
// The C++ code has made copies of the asset and string data, so free our copies.
|
||||
CanvasKit._free(namesPtr);
|
||||
|
@ -89,8 +89,11 @@ private:
|
||||
class ManagedAnimation final : public SkRefCnt {
|
||||
public:
|
||||
static sk_sp<ManagedAnimation> Make(const std::string& json,
|
||||
sk_sp<skottie::ResourceProvider> rp) {
|
||||
auto mgr = std::make_unique<skottie_utils::CustomPropertyManager>();
|
||||
sk_sp<skottie::ResourceProvider> rp,
|
||||
std::string prop_prefix) {
|
||||
auto mgr = std::make_unique<skottie_utils::CustomPropertyManager>(
|
||||
skottie_utils::CustomPropertyManager::Mode::kCollapseProperties,
|
||||
prop_prefix.empty() ? nullptr : prop_prefix.c_str());
|
||||
static constexpr char kInterceptPrefix[] = "__";
|
||||
auto pinterceptor =
|
||||
sk_make_sp<skottie_utils::ExternalAnimationPrecompInterceptor>(rp, kInterceptPrefix);
|
||||
@ -243,7 +246,8 @@ EMSCRIPTEN_BINDINGS(Skottie) {
|
||||
size_t assetCount,
|
||||
uintptr_t /* char** */ nptr,
|
||||
uintptr_t /* uint8_t** */ dptr,
|
||||
uintptr_t /* size_t* */ sptr)
|
||||
uintptr_t /* size_t* */ sptr,
|
||||
std::string prop_prefix)
|
||||
->sk_sp<ManagedAnimation> {
|
||||
// See the comment in canvaskit_bindings.cpp about the use of uintptr_t
|
||||
const auto assetNames = reinterpret_cast<char** >(nptr);
|
||||
@ -260,8 +264,9 @@ EMSCRIPTEN_BINDINGS(Skottie) {
|
||||
}
|
||||
|
||||
return ManagedAnimation::Make(json,
|
||||
skresources::DataURIResourceProviderProxy::Make(
|
||||
SkottieAssetProvider::Make(std::move(assets))));
|
||||
skresources::DataURIResourceProviderProxy::Make(
|
||||
SkottieAssetProvider::Make(std::move(assets))),
|
||||
prop_prefix);
|
||||
}));
|
||||
constant("managed_skottie", true);
|
||||
#endif // SK_INCLUDE_MANAGED_SKOTTIE
|
||||
|
@ -15,23 +15,34 @@ public:
|
||||
|
||||
void onColorProperty(const char node_name[],
|
||||
const LazyHandle<skottie::ColorPropertyHandle>& c) override {
|
||||
const auto markedKey = CustomPropertyManager::AcceptKey(node_name);
|
||||
const auto key = markedKey.empty() ? markedKey : fMgr->fCurrentNode + ".Color";
|
||||
fMgr->fColorMap[key].push_back(c());
|
||||
const auto key = fMgr->acceptKey(node_name, ".Color");
|
||||
if (!key.empty()) {
|
||||
fMgr->fColorMap[key].push_back(c());
|
||||
}
|
||||
}
|
||||
|
||||
void onOpacityProperty(const char node_name[],
|
||||
const LazyHandle<skottie::OpacityPropertyHandle>& o) override {
|
||||
const auto markedKey = CustomPropertyManager::AcceptKey(node_name);
|
||||
const auto key = markedKey.empty() ? markedKey : fMgr->fCurrentNode + ".Opacity";
|
||||
fMgr->fOpacityMap[key].push_back(o());
|
||||
const auto key = fMgr->acceptKey(node_name, ".Opacity");
|
||||
if (!key.empty()) {
|
||||
fMgr->fOpacityMap[key].push_back(o());
|
||||
}
|
||||
}
|
||||
|
||||
void onTransformProperty(const char node_name[],
|
||||
const LazyHandle<skottie::TransformPropertyHandle>& t) override {
|
||||
const auto markedKey = CustomPropertyManager::AcceptKey(node_name);
|
||||
const auto key = markedKey.empty() ? markedKey : fMgr->fCurrentNode + ".Transform";
|
||||
fMgr->fTransformMap[key].push_back(t());
|
||||
const auto key = fMgr->acceptKey(node_name, ".Transform");
|
||||
if (!key.empty()) {
|
||||
fMgr->fTransformMap[key].push_back(t());
|
||||
}
|
||||
}
|
||||
|
||||
void onTextProperty(const char node_name[],
|
||||
const LazyHandle<skottie::TextPropertyHandle>& t) override {
|
||||
const auto key = fMgr->acceptKey(node_name, ".Text");
|
||||
if (!key.empty()) {
|
||||
fMgr->fTextMap[key].push_back(t());
|
||||
}
|
||||
}
|
||||
|
||||
void onEnterNode(const char node_name[]) override {
|
||||
@ -48,14 +59,6 @@ public:
|
||||
: "";
|
||||
}
|
||||
|
||||
void onTextProperty(const char node_name[],
|
||||
const LazyHandle<skottie::TextPropertyHandle>& t) override {
|
||||
const auto key = CustomPropertyManager::AcceptKey(node_name);
|
||||
if (!key.empty()) {
|
||||
fMgr->fTextMap[key].push_back(t());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
CustomPropertyManager* fMgr;
|
||||
};
|
||||
@ -65,22 +68,32 @@ public:
|
||||
explicit MarkerInterceptor(CustomPropertyManager* mgr) : fMgr(mgr) {}
|
||||
|
||||
void onMarker(const char name[], float t0, float t1) override {
|
||||
const auto key = CustomPropertyManager::AcceptKey(name);
|
||||
if (!key.empty()) {
|
||||
fMgr->fMarkers.push_back({ std::move(key), t0, t1 });
|
||||
}
|
||||
// collect all markers
|
||||
fMgr->fMarkers.push_back({ std::string(name), t0, t1 });
|
||||
}
|
||||
|
||||
private:
|
||||
CustomPropertyManager* fMgr;
|
||||
};
|
||||
|
||||
CustomPropertyManager::CustomPropertyManager()
|
||||
: fPropertyInterceptor(sk_make_sp<PropertyInterceptor>(this))
|
||||
CustomPropertyManager::CustomPropertyManager(Mode mode, const char* prefix)
|
||||
: fMode(mode)
|
||||
, fPrefix(prefix ? prefix : "$")
|
||||
, fPropertyInterceptor(sk_make_sp<PropertyInterceptor>(this))
|
||||
, fMarkerInterceptor(sk_make_sp<MarkerInterceptor>(this)) {}
|
||||
|
||||
CustomPropertyManager::~CustomPropertyManager() = default;
|
||||
|
||||
std::string CustomPropertyManager::acceptKey(const char* name, const char* suffix) const {
|
||||
if (!SkStrStartsWith(name, fPrefix.c_str())) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return fMode == Mode::kCollapseProperties
|
||||
? std::string(name)
|
||||
: fCurrentNode + suffix;
|
||||
}
|
||||
|
||||
sk_sp<skottie::PropertyObserver> CustomPropertyManager::getPropertyObserver() const {
|
||||
return fPropertyInterceptor;
|
||||
}
|
||||
|
@ -33,7 +33,14 @@ namespace skottie_utils {
|
||||
*/
|
||||
class CustomPropertyManager final {
|
||||
public:
|
||||
CustomPropertyManager();
|
||||
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;
|
||||
@ -70,16 +77,7 @@ private:
|
||||
class PropertyInterceptor;
|
||||
class MarkerInterceptor;
|
||||
|
||||
static std::string AcceptKey(const char* name) {
|
||||
static constexpr char kPrefix = '$';
|
||||
|
||||
return (name[0] == kPrefix && name[1] != '\0')
|
||||
? std::string(name + 1)
|
||||
: std::string();
|
||||
}
|
||||
|
||||
sk_sp<PropertyInterceptor> fPropertyInterceptor;
|
||||
sk_sp<MarkerInterceptor> fMarkerInterceptor;
|
||||
std::string acceptKey(const char*, const char*) const;
|
||||
|
||||
template <typename T>
|
||||
using PropGroup = std::vector<std::unique_ptr<T>>;
|
||||
@ -96,6 +94,12 @@ private:
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user