mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-07 21:23:32 +00:00
lottie: add custom layer effect with expressions support
effect(name) / effect(index) effects finds the effect by its name in the Effect Controls panel. The name can be the default name or a user-defined name. If multiple effects have the same name, the effect closest to the top of the Effect Controls panel is used. example: - effect("Fast Blur")("Blurriness") issue: https://github.com/thorvg/thorvg/issues/3115
This commit is contained in:
parent
fbe10255d7
commit
d3afebfdec
10 changed files with 55154 additions and 86 deletions
4213
examples/resources/lottie/expressions/10456.json
Normal file
4213
examples/resources/lottie/expressions/10456.json
Normal file
File diff suppressed because it is too large
Load diff
50214
examples/resources/lottie/expressions/16447.json
Normal file
50214
examples/resources/lottie/expressions/16447.json
Normal file
File diff suppressed because it is too large
Load diff
486
examples/resources/lottie/expressions/4128.json
Normal file
486
examples/resources/lottie/expressions/4128.json
Normal file
|
@ -0,0 +1,486 @@
|
|||
{
|
||||
"v": "5.4.3",
|
||||
"fr": 60,
|
||||
"ip": 0,
|
||||
"op": 100,
|
||||
"w": 500,
|
||||
"h": 500,
|
||||
"nm": "ProgressCircle-lottie",
|
||||
"ddd": 0,
|
||||
"assets": [],
|
||||
"layers": [
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 1,
|
||||
"ty": 3,
|
||||
"nm": "Counter",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
250,
|
||||
250,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
117.183,
|
||||
117.183,
|
||||
100
|
||||
],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"ef": [
|
||||
{
|
||||
"ty": 5,
|
||||
"nm": "Slider Control",
|
||||
"np": 3,
|
||||
"mn": "ADBE Slider Control",
|
||||
"ix": 1,
|
||||
"en": 1,
|
||||
"ef": [
|
||||
{
|
||||
"ty": 0,
|
||||
"nm": "Slider",
|
||||
"mn": "ADBE Slider Control-0001",
|
||||
"ix": 1,
|
||||
"v": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0.833
|
||||
],
|
||||
"y": [
|
||||
0.833
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.167
|
||||
],
|
||||
"y": [
|
||||
0.167
|
||||
]
|
||||
},
|
||||
"n": [
|
||||
"0p833_0p833_0p167_0p167"
|
||||
],
|
||||
"t": 0,
|
||||
"s": [
|
||||
0
|
||||
],
|
||||
"e": [
|
||||
100
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 100
|
||||
}
|
||||
],
|
||||
"ix": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 100,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
},
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 2,
|
||||
"ty": 4,
|
||||
"nm": "Shape Layer 2",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
202,
|
||||
194,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
126.352,
|
||||
126.352,
|
||||
100
|
||||
],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"d": 1,
|
||||
"ty": "el",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
342.324,
|
||||
342.324
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"nm": "Ellipse Path 1",
|
||||
"mn": "ADBE Vector Shape - Ellipse",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "st",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
1,
|
||||
0.4,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 4
|
||||
},
|
||||
"w": {
|
||||
"a": 0,
|
||||
"k": 20,
|
||||
"ix": 5
|
||||
},
|
||||
"lc": 1,
|
||||
"lj": 1,
|
||||
"ml": 4,
|
||||
"ml2": {
|
||||
"a": 0,
|
||||
"k": 4,
|
||||
"ix": 8
|
||||
},
|
||||
"bm": 0,
|
||||
"nm": "Stroke 1",
|
||||
"mn": "ADBE Vector Graphic - Stroke",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
38.162,
|
||||
44.162
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 6
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 7
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 4
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"nm": "Transform"
|
||||
}
|
||||
],
|
||||
"nm": "Ellipse 1",
|
||||
"np": 3,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tm",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 1
|
||||
},
|
||||
"e": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2,
|
||||
"x": "var $bm_rt;\n$bm_rt = thisComp.layer('Counter').effect('Slider Control')('Slider');"
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 3
|
||||
},
|
||||
"m": 1,
|
||||
"ix": 2,
|
||||
"nm": "Trim Paths 1",
|
||||
"mn": "ADBE Vector Filter - Trim",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 100,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
},
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 3,
|
||||
"ty": 4,
|
||||
"nm": "Shape Layer 1",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
202,
|
||||
194,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
126.352,
|
||||
126.352,
|
||||
100
|
||||
],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"d": 1,
|
||||
"ty": "el",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
342.324,
|
||||
342.324
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"nm": "Ellipse Path 1",
|
||||
"mn": "ADBE Vector Shape - Ellipse",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "st",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
1
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 4
|
||||
},
|
||||
"w": {
|
||||
"a": 0,
|
||||
"k": 20,
|
||||
"ix": 5
|
||||
},
|
||||
"lc": 1,
|
||||
"lj": 1,
|
||||
"ml": 4,
|
||||
"ml2": {
|
||||
"a": 0,
|
||||
"k": 4,
|
||||
"ix": 8
|
||||
},
|
||||
"bm": 0,
|
||||
"nm": "Stroke 1",
|
||||
"mn": "ADBE Vector Graphic - Stroke",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
38.162,
|
||||
44.162
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 6
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 7
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 4
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"nm": "Transform"
|
||||
}
|
||||
],
|
||||
"nm": "Ellipse 1",
|
||||
"np": 3,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 100,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
}
|
||||
],
|
||||
"markers": []
|
||||
}
|
1
examples/resources/lottie/expressions/layereffect.json
Normal file
1
examples/resources/lottie/expressions/layereffect.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -35,7 +35,10 @@
|
|||
struct ExpContent
|
||||
{
|
||||
LottieExpression* exp;
|
||||
LottieObject* obj;
|
||||
union {
|
||||
LottieObject* obj;
|
||||
LottieEffect* effect;
|
||||
};
|
||||
float frameNo;
|
||||
};
|
||||
|
||||
|
@ -58,12 +61,12 @@ static const char* EXP_EFFECT= "effect";
|
|||
static LottieExpressions* exps = nullptr; //singleton instance engine
|
||||
|
||||
|
||||
static ExpContent* _expcontent(LottieExpression* exp, float frameNo, LottieObject* obj)
|
||||
static ExpContent* _expcontent(LottieExpression* exp, float frameNo, void* obj)
|
||||
{
|
||||
auto data = tvg::malloc<ExpContent*>(sizeof(ExpContent));
|
||||
data->exp = exp;
|
||||
data->frameNo = frameNo;
|
||||
data->obj = obj;
|
||||
data->obj = (LottieObject*)obj;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -87,6 +90,22 @@ static jerry_value_t _point2d(const Point& pt)
|
|||
}
|
||||
|
||||
|
||||
static jerry_value_t _color(RGB24 rgb)
|
||||
{
|
||||
auto value = jerry_object();
|
||||
auto r = jerry_number(rgb.rgb[0]);
|
||||
auto g = jerry_number(rgb.rgb[1]);
|
||||
auto b = jerry_number(rgb.rgb[2]);
|
||||
jerry_object_set_index(value, 0, r);
|
||||
jerry_object_set_index(value, 1, g);
|
||||
jerry_object_set_index(value, 2, b);
|
||||
jerry_value_free(r);
|
||||
jerry_value_free(g);
|
||||
jerry_value_free(b);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
static Point _point2d(jerry_value_t obj)
|
||||
{
|
||||
auto v1 = jerry_object_get_index(obj, 0);
|
||||
|
@ -97,6 +116,21 @@ static Point _point2d(jerry_value_t obj)
|
|||
return pt;
|
||||
}
|
||||
|
||||
static RGB24 _color(jerry_value_t obj)
|
||||
{
|
||||
RGB24 out;
|
||||
auto r = jerry_object_get_index(obj, 0);
|
||||
auto g = jerry_object_get_index(obj, 1);
|
||||
auto b = jerry_object_get_index(obj, 2);
|
||||
out.rgb[0] = jerry_value_as_number(r);
|
||||
out.rgb[1] = jerry_value_as_number(g);
|
||||
out.rgb[2] = jerry_value_as_number(b);
|
||||
jerry_value_free(r);
|
||||
jerry_value_free(g);
|
||||
jerry_value_free(b);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
static void contentFree(void *native_p, struct jerry_object_native_info_t *info_p)
|
||||
{
|
||||
|
@ -139,26 +173,19 @@ static jerry_value_t _toComp(const jerry_call_info_t* info, const jerry_value_t
|
|||
static jerry_value_t _value(float frameNo, LottieProperty* property)
|
||||
{
|
||||
switch (property->type) {
|
||||
case LottieProperty::Type::Float: {
|
||||
return jerry_number((*static_cast<LottieFloat*>(property))(frameNo));
|
||||
}
|
||||
case LottieProperty::Type::Scalar: {
|
||||
return _point2d((*static_cast<LottieScalar*>(property))(frameNo));
|
||||
}
|
||||
case LottieProperty::Type::Vector: {
|
||||
return _point2d((*static_cast<LottieVector*>(property))(frameNo));
|
||||
}
|
||||
case LottieProperty::Type::PathSet: {
|
||||
case LottieProperty::Type::Integer: return jerry_number((*static_cast<LottieInteger*>(property))(frameNo));
|
||||
case LottieProperty::Type::Float: return jerry_number((*static_cast<LottieFloat*>(property))(frameNo));
|
||||
case LottieProperty::Type::Scalar: return _point2d((*static_cast<LottieScalar*>(property))(frameNo));
|
||||
case LottieProperty::Type::Vector: return _point2d((*static_cast<LottieVector*>(property))(frameNo));
|
||||
case LottieProperty::Type::PathSet:
|
||||
{
|
||||
auto value = jerry_object();
|
||||
jerry_object_set_native_ptr(value, nullptr, property);
|
||||
return value;
|
||||
}
|
||||
case LottieProperty::Type::Opacity: {
|
||||
return jerry_number((*static_cast<LottieOpacity*>(property))(frameNo));
|
||||
}
|
||||
default: {
|
||||
TVGERR("LOTTIE", "Non supported type for value? = %d", (int) property->type);
|
||||
}
|
||||
case LottieProperty::Type::Color: return _color((*static_cast<LottieColor*>(property))(frameNo));
|
||||
case LottieProperty::Type::Opacity: return jerry_number((*static_cast<LottieOpacity*>(property))(frameNo));
|
||||
default: TVGERR("LOTTIE", "Non supported type for value? = %d", (int) property->type);
|
||||
}
|
||||
return jerry_undefined();
|
||||
}
|
||||
|
@ -259,6 +286,44 @@ static jerry_value_t _buildTrimpath(LottieTrimpath* trimpath, float frameNo)
|
|||
}
|
||||
|
||||
|
||||
static jerry_value_t _effectProperty(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
|
||||
{
|
||||
auto data = static_cast<ExpContent*>(jerry_object_get_native_ptr(info->function, &freeCb));
|
||||
auto name = _name(args[0]);
|
||||
auto property = static_cast<LottieFxCustom*>(data->effect)->property(name);
|
||||
tvg::free(name);
|
||||
|
||||
if (!property) return jerry_undefined();
|
||||
|
||||
return _value(data->frameNo, property);
|
||||
}
|
||||
|
||||
|
||||
static jerry_value_t _effect(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
|
||||
{
|
||||
auto data = static_cast<ExpContent*>(jerry_object_get_native_ptr(info->function, &freeCb));
|
||||
auto layer = static_cast<LottieLayer*>(data->obj);
|
||||
LottieEffect* effect = nullptr;
|
||||
|
||||
//either name or index
|
||||
if (jerry_value_is_string(args[0])) {
|
||||
auto name = _name(args[0]);
|
||||
effect = layer->effectById(djb2Encode(name));
|
||||
tvg::free(name);
|
||||
} else {
|
||||
effect = layer->effectByIdx((int16_t)jerry_value_as_int32(args[0]));
|
||||
}
|
||||
|
||||
if (!effect) return jerry_undefined();
|
||||
|
||||
//find a effect property
|
||||
auto obj = jerry_function_external(_effectProperty);
|
||||
jerry_object_set_native_ptr(obj, &freeCb, _expcontent(data->exp, data->frameNo, effect));
|
||||
jerry_object_set_sz(obj, "", obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
static void _buildLayer(jerry_value_t context, float frameNo, LottieLayer* layer, LottieLayer* comp, LottieExpression* exp)
|
||||
{
|
||||
auto width = jerry_number(layer->w);
|
||||
|
@ -345,6 +410,11 @@ static void _buildLayer(jerry_value_t context, float frameNo, LottieLayer* layer
|
|||
jerry_object_set_sz(context, EXP_CONTENT, content);
|
||||
jerry_object_set_native_ptr(content, &freeCb, _expcontent(exp, frameNo, layer));
|
||||
jerry_value_free(content);
|
||||
|
||||
auto effect = jerry_function_external(_effect);
|
||||
jerry_object_set_sz(context, EXP_EFFECT, effect);
|
||||
jerry_object_set_native_ptr(effect, &freeCb, _expcontent(exp, frameNo, layer));
|
||||
jerry_value_free(effect);
|
||||
}
|
||||
|
||||
|
||||
|
@ -535,14 +605,6 @@ static jerry_value_t _rad2deg(const jerry_call_info_t* info, const jerry_value_t
|
|||
}
|
||||
|
||||
|
||||
static jerry_value_t _effect(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
|
||||
{
|
||||
TVGLOG("LOTTIE", "effect is not supported in expressions!");
|
||||
|
||||
return jerry_undefined();
|
||||
}
|
||||
|
||||
|
||||
static jerry_value_t _fromCompToSurface(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
|
||||
{
|
||||
TVGLOG("LOTTIE", "fromCompToSurface is not supported in expressions!");
|
||||
|
@ -1060,6 +1122,11 @@ static void _buildProperty(float frameNo, jerry_value_t context, LottieExpressio
|
|||
|
||||
//expansions per types
|
||||
if (exp->property->type == LottieProperty::Type::PathSet) _buildPath(context, exp);
|
||||
|
||||
auto effect = jerry_function_external(_effect);
|
||||
jerry_object_set_sz(context, EXP_EFFECT, effect);
|
||||
jerry_object_set_native_ptr(effect, &freeCb, _expcontent(exp, frameNo, exp->layer));
|
||||
jerry_value_free(effect);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1266,10 +1333,6 @@ jerry_value_t LottieExpressions::buildGlobal()
|
|||
thisProperty = jerry_object();
|
||||
jerry_object_set_sz(global, "thisProperty", thisProperty);
|
||||
|
||||
auto effect = jerry_function_external(_effect);
|
||||
jerry_object_set_sz(global, EXP_EFFECT, effect);
|
||||
jerry_value_free(effect);
|
||||
|
||||
auto fromCompToSurface = jerry_function_external(_fromCompToSurface);
|
||||
jerry_object_set_sz(global, "fromCompToSurface", fromCompToSurface);
|
||||
jerry_value_free(fromCompToSurface);
|
||||
|
@ -1397,4 +1460,16 @@ void LottieExpressions::retrieve(LottieExpressions* instance)
|
|||
}
|
||||
|
||||
|
||||
Point LottieExpressions::toPoint2d(jerry_value_t obj)
|
||||
{
|
||||
return _point2d(obj);
|
||||
}
|
||||
|
||||
|
||||
RGB24 LottieExpressions::toColor(jerry_value_t obj)
|
||||
{
|
||||
return _color(obj);
|
||||
}
|
||||
|
||||
|
||||
#endif //THORVG_LOTTIE_EXPRESSIONS_SUPPORT
|
||||
|
|
|
@ -63,12 +63,7 @@ public:
|
|||
if (auto prop = static_cast<Property*>(jerry_object_get_native_ptr(bm_rt, nullptr))) {
|
||||
out = (*prop)(frameNo);
|
||||
} else {
|
||||
auto x = jerry_object_get_index(bm_rt, 0);
|
||||
auto y = jerry_object_get_index(bm_rt, 1);
|
||||
out.x = jerry_value_as_number(x);
|
||||
out.y = jerry_value_as_number(y);
|
||||
jerry_value_free(x);
|
||||
jerry_value_free(y);
|
||||
out = toPoint2d(bm_rt);
|
||||
}
|
||||
jerry_value_free(bm_rt);
|
||||
return true;
|
||||
|
@ -83,15 +78,7 @@ public:
|
|||
if (auto color = static_cast<Property*>(jerry_object_get_native_ptr(bm_rt, nullptr))) {
|
||||
out = (*color)(frameNo);
|
||||
} else {
|
||||
auto r = jerry_object_get_index(bm_rt, 0);
|
||||
auto g = jerry_object_get_index(bm_rt, 1);
|
||||
auto b = jerry_object_get_index(bm_rt, 2);
|
||||
out.rgb[0] = REMAP255(jerry_value_as_number(r));
|
||||
out.rgb[1] = REMAP255(jerry_value_as_number(g));
|
||||
out.rgb[2] = REMAP255(jerry_value_as_number(b));
|
||||
jerry_value_free(r);
|
||||
jerry_value_free(g);
|
||||
jerry_value_free(b);
|
||||
out = toColor(bm_rt);
|
||||
}
|
||||
jerry_value_free(bm_rt);
|
||||
return true;
|
||||
|
@ -156,6 +143,9 @@ private:
|
|||
void buildGlobal(LottieExpression* exp);
|
||||
void buildWritables(LottieExpression* exp);
|
||||
|
||||
Point toPoint2d(jerry_value_t obj);
|
||||
RGB24 toColor(jerry_value_t obj);
|
||||
|
||||
//global object, attributes, methods
|
||||
jerry_value_t global;
|
||||
jerry_value_t comp;
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
#ifndef _TVG_LOTTIE_MODEL_H_
|
||||
#define _TVG_LOTTIE_MODEL_H_
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "tvgCommon.h"
|
||||
#include "tvgStr.h"
|
||||
#include "tvgCompressor.h"
|
||||
#include "tvgRender.h"
|
||||
#include "tvgLottieProperty.h"
|
||||
#include "tvgLottieRenderPooler.h"
|
||||
|
@ -83,13 +83,63 @@ struct LottieStroke
|
|||
|
||||
struct LottieEffect
|
||||
{
|
||||
enum Type : uint8_t {Tint = 20, Fill, Stroke, Tritone, DropShadow = 25, GaussianBlur = 29};
|
||||
enum Type : uint8_t {Custom = 5, Tint = 20, Fill, Stroke, Tritone, DropShadow = 25, GaussianBlur = 29};
|
||||
|
||||
virtual ~LottieEffect() {}
|
||||
|
||||
unsigned long id;
|
||||
int16_t ix;
|
||||
Type type;
|
||||
bool enable = false;
|
||||
};
|
||||
|
||||
|
||||
struct LottieFxCustom : LottieEffect
|
||||
{
|
||||
char* name = nullptr;
|
||||
Array<LottieProperty*> props;
|
||||
|
||||
LottieFxCustom()
|
||||
{
|
||||
type = LottieEffect::Custom;
|
||||
}
|
||||
|
||||
~LottieFxCustom()
|
||||
{
|
||||
ARRAY_FOREACH(p, props) delete(*p);
|
||||
}
|
||||
|
||||
LottieProperty* property(int type)
|
||||
{
|
||||
LottieProperty* prop = nullptr;
|
||||
|
||||
switch (type) {
|
||||
case 0: //slider
|
||||
case 1: prop = new LottieFloat; break; //angle
|
||||
case 2: prop = new LottieColor; break; //color
|
||||
case 3: prop = new LottieVector; break; //point
|
||||
case 4: //checkbox
|
||||
case 7: //dropdown
|
||||
case 10: prop = new LottieInteger; break; //effect layer
|
||||
case 6: TVGLOG("LOTTIE", "custom ignored?"); break;
|
||||
default:
|
||||
TVGLOG("LOTTIE", "missing custom property = %d\n", type);
|
||||
return nullptr;
|
||||
}
|
||||
if (prop) props.push(prop);
|
||||
return prop;
|
||||
}
|
||||
|
||||
LottieProperty* property(const char* name)
|
||||
{
|
||||
auto ix = static_cast<uint32_t>(djb2Encode(name));
|
||||
ARRAY_FOREACH(p, props) {
|
||||
if ((*p)->ix == ix) return *p;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
struct LottieFxFill : LottieEffect
|
||||
{
|
||||
//LottieInteger mask;
|
||||
|
@ -223,7 +273,7 @@ struct LottieObject
|
|||
virtual bool mergeable() { return false; }
|
||||
virtual LottieProperty* property(uint16_t ix) { return nullptr; }
|
||||
|
||||
unsigned long id = 0;
|
||||
unsigned long id = 0; //unique id by name generated by djb2 encoding
|
||||
Type type;
|
||||
bool hidden = false; //remove?
|
||||
};
|
||||
|
@ -944,6 +994,23 @@ struct LottieLayer : LottieGroup
|
|||
bool autoOrient = false;
|
||||
bool matteSrc = false;
|
||||
|
||||
LottieEffect* effectById(unsigned long id)
|
||||
{
|
||||
ARRAY_FOREACH(p, effects) {
|
||||
if (id == (*p)->id) return *p;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LottieEffect* effectByIdx(int16_t ix)
|
||||
{
|
||||
ARRAY_FOREACH(p, effects) {
|
||||
if (ix == (*p)->ix) return *p;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
LottieLayer* layerById(unsigned long id)
|
||||
{
|
||||
ARRAY_FOREACH(p, children) {
|
||||
|
|
|
@ -60,6 +60,7 @@ LottieExpression* LottieParser::getExpression(char* code, LottieComposition* com
|
|||
LottieEffect* LottieParser::getEffect(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case LottieEffect::Custom: return new LottieFxCustom;
|
||||
case LottieEffect::Tint: return new LottieFxTint;
|
||||
case LottieEffect::Fill: return new LottieFxFill;
|
||||
case LottieEffect::Stroke: return new LottieFxStroke;
|
||||
|
@ -1255,25 +1256,60 @@ void LottieParser::parseMasks(LottieLayer* layer)
|
|||
}
|
||||
|
||||
|
||||
void LottieParser::parseEffect(LottieEffect* effect, void(LottieParser::*func)(LottieEffect*, int))
|
||||
bool LottieParser::parseEffect(LottieEffect* effect, void(LottieParser::*func)(LottieEffect*, int))
|
||||
{
|
||||
int idx = 0;
|
||||
//custom effect expects dynamic property allocations
|
||||
auto custom = (effect->type == LottieEffect::Custom) ? true : false;
|
||||
LottieProperty* property = nullptr;
|
||||
|
||||
enterArray();
|
||||
int idx = 0;
|
||||
while (nextArrayValue()) {
|
||||
enterObject();
|
||||
while (auto key = nextObjectKey()) {
|
||||
if (KEY_AS("v")) {
|
||||
if (custom && KEY_AS("ty")) {
|
||||
property = static_cast<LottieFxCustom*>(effect)->property(getInt());
|
||||
} else if (KEY_AS("v")) {
|
||||
if (peekType() == kObjectType) {
|
||||
enterObject();
|
||||
while (auto key = nextObjectKey()) {
|
||||
if (KEY_AS("k")) (this->*func)(effect, idx);
|
||||
if (KEY_AS("k")) (this->*func)(effect, idx++);
|
||||
else skip();
|
||||
}
|
||||
++idx;
|
||||
} else skip();
|
||||
} else if (property && KEY_AS("nm")) {
|
||||
property->ix = djb2Encode(getString());
|
||||
} else skip();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void LottieParser::parseCustom(LottieEffect* effect, int idx)
|
||||
{
|
||||
if ((uint32_t)idx >= static_cast<LottieFxCustom*>(effect)->props.count) {
|
||||
TVGERR("LOTTIE", "Parsing error in Custom effect!");
|
||||
return;
|
||||
}
|
||||
|
||||
auto prop = static_cast<LottieFxCustom*>(effect)->props[idx];
|
||||
|
||||
switch (prop->type) {
|
||||
case LottieProperty::Type::Integer: {
|
||||
parsePropertyInternal(*static_cast<LottieInteger*>(prop)); break;
|
||||
}
|
||||
case LottieProperty::Type::Float: {
|
||||
parsePropertyInternal(*static_cast<LottieFloat*>(prop)); break;
|
||||
}
|
||||
case LottieProperty::Type::Vector: {
|
||||
parsePropertyInternal(*static_cast<LottieVector*>(prop)); break;
|
||||
}
|
||||
case LottieProperty::Type::Color: {
|
||||
parsePropertyInternal(*static_cast<LottieColor*>(prop)); break;
|
||||
}
|
||||
default: TVGLOG("LOTTIE", "Missing Property Type? = %d", (int) prop->type); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1348,34 +1384,17 @@ void LottieParser::parseStroke(LottieEffect* effect, int idx)
|
|||
}
|
||||
|
||||
|
||||
void LottieParser::parseEffect(LottieEffect* effect)
|
||||
bool LottieParser::parseEffect(LottieEffect* effect)
|
||||
{
|
||||
switch (effect->type) {
|
||||
case LottieEffect::Tint: {
|
||||
parseEffect(effect, &LottieParser::parseTint);
|
||||
break;
|
||||
}
|
||||
case LottieEffect::Fill: {
|
||||
parseEffect(effect, &LottieParser::parseFill);
|
||||
break;
|
||||
}
|
||||
case LottieEffect::Stroke: {
|
||||
parseEffect(effect, &LottieParser::parseStroke);
|
||||
break;
|
||||
}
|
||||
case LottieEffect::Tritone: {
|
||||
parseEffect(effect, &LottieParser::parseTritone);
|
||||
break;
|
||||
}
|
||||
case LottieEffect::DropShadow: {
|
||||
parseEffect(effect, &LottieParser::parseDropShadow);
|
||||
break;
|
||||
}
|
||||
case LottieEffect::GaussianBlur: {
|
||||
parseEffect(effect, &LottieParser::parseGaussianBlur);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
case LottieEffect::Custom: return parseEffect(effect, &LottieParser::parseCustom);
|
||||
case LottieEffect::Tint: return parseEffect(effect, &LottieParser::parseTint);
|
||||
case LottieEffect::Fill: return parseEffect(effect, &LottieParser::parseFill);
|
||||
case LottieEffect::Stroke: return parseEffect(effect, &LottieParser::parseStroke);
|
||||
case LottieEffect::Tritone: return parseEffect(effect, &LottieParser::parseTritone);
|
||||
case LottieEffect::DropShadow: return parseEffect(effect, &LottieParser::parseDropShadow);
|
||||
case LottieEffect::GaussianBlur: return parseEffect(effect, &LottieParser::parseGaussianBlur);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1395,6 +1414,8 @@ void LottieParser::parseEffects(LottieLayer* layer)
|
|||
if (!effect) break;
|
||||
else invalid = false;
|
||||
}
|
||||
else if (effect && KEY_AS("nm")) effect->id = djb2Encode(getString());
|
||||
else if (effect && KEY_AS("ix")) effect->ix = getInt();
|
||||
else if (effect && KEY_AS("en")) effect->enable = getInt();
|
||||
else if (effect && KEY_AS("ef")) parseEffect(effect);
|
||||
else skip();
|
||||
|
|
|
@ -99,7 +99,8 @@ private:
|
|||
void parseFontData(LottieFont* font, const char* data);
|
||||
LottieMarker* parseMarker();
|
||||
|
||||
void parseEffect(LottieEffect* effect, void(LottieParser::*func)(LottieEffect*, int));
|
||||
bool parseEffect(LottieEffect* effect, void(LottieParser::*func)(LottieEffect*, int));
|
||||
void parseCustom(LottieEffect* effect, int idx);
|
||||
void parseStroke(LottieEffect* effect, int idx);
|
||||
void parseTritone(LottieEffect* effect, int idx);
|
||||
void parseTint(LottieEffect* effect, int idx);
|
||||
|
@ -125,7 +126,7 @@ private:
|
|||
void parseFonts();
|
||||
void parseChars(Array<LottieGlyph*>& glyphs);
|
||||
void parseMarkers();
|
||||
void parseEffect(LottieEffect* effect);
|
||||
bool parseEffect(LottieEffect* effect);
|
||||
void postProcess(Array<LottieGlyph*>& glyphs);
|
||||
|
||||
//Current parsing context
|
||||
|
|
|
@ -186,14 +186,15 @@ struct LottieExpression
|
|||
//Property would have an either keyframes or single value.
|
||||
struct LottieProperty
|
||||
{
|
||||
enum class Type : uint8_t { Invalid = 0, Float, Integer, Scalar, Vector, PathSet, Color, Opacity, ColorStop, TextDoc, Image};
|
||||
enum class Type : uint8_t {Invalid = 0, Integer, Float, Scalar, Vector, PathSet, Color, Opacity, ColorStop, TextDoc, Image};
|
||||
|
||||
LottieExpression* exp = nullptr;
|
||||
uint32_t ix; //property index (used as a name id for indexing by custom layer effect as well)
|
||||
Type type;
|
||||
uint8_t ix; //property index
|
||||
|
||||
LottieProperty(Type type = Type::Invalid) : type(type) {}
|
||||
virtual ~LottieProperty() {}
|
||||
|
||||
virtual uint32_t frameCnt() = 0;
|
||||
virtual uint32_t nearest(float frameNo) = 0;
|
||||
virtual float frameNo(int32_t key) = 0;
|
||||
|
@ -1007,5 +1008,4 @@ using LottieVector = LottieGenericProperty<LottieVectorFrame<Point>, Point, Lott
|
|||
using LottieColor = LottieGenericProperty<LottieScalarFrame<RGB24>, RGB24, LottieProperty::Type::Color>;
|
||||
using LottieOpacity = LottieGenericProperty<LottieScalarFrame<uint8_t>, uint8_t, LottieProperty::Type::Opacity>;
|
||||
|
||||
|
||||
#endif //_TVG_LOTTIE_PROPERTY_H_
|
||||
|
|
Loading…
Add table
Reference in a new issue