diff --git a/src/loaders/lottie/tvgLottieExpressions.cpp b/src/loaders/lottie/tvgLottieExpressions.cpp index 4075e0be..25121f33 100644 --- a/src/loaders/lottie/tvgLottieExpressions.cpp +++ b/src/loaders/lottie/tvgLottieExpressions.cpp @@ -100,12 +100,56 @@ static unsigned long _idByName(jerry_value_t args) static jerry_value_t _toComp(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt) { - TVGERR("LOTTIE", "toComp is not supported in expressions!"); + TVGLOG("LOTTIE", "toComp is not supported in expressions!"); return jerry_undefined(); } +static jerry_value_t _value(float frameNo, LottieProperty* property) +{ + switch (property->type) { + case LottieProperty::Type::Point: { + auto value = jerry_object(); + auto pos = (*static_cast(property))(frameNo); + auto val1 = jerry_number(pos.x); + auto val2 = jerry_number(pos.y); + jerry_object_set_index(value, 0, val1); + jerry_object_set_index(value, 1, val2); + jerry_value_free(val1); + jerry_value_free(val2); + return value; + } + case LottieProperty::Type::Float: { + return jerry_number((*static_cast(property))(frameNo)); + } + case LottieProperty::Type::Opacity: { + return jerry_number((*static_cast(property))(frameNo)); + } + case LottieProperty::Type::PathSet: { + auto value = jerry_object(); + jerry_object_set_native_ptr(value, nullptr, property); + return value; + } + case LottieProperty::Type::Position: { + auto value = jerry_object(); + auto pos = (*static_cast(property))(frameNo); + auto val1 = jerry_number(pos.x); + auto val2 = jerry_number(pos.y); + jerry_object_set_index(value, 0, val1); + jerry_object_set_index(value, 1, val2); + jerry_value_free(val1); + jerry_value_free(val2); + return value; + } + default: { + TVGERR("LOTTIE", "Non supported type for value? = %d", (int) property->type); + } + } + return jerry_undefined(); +} + + static void _buildTransform(jerry_value_t context, float frameNo, LottieTransform* transform) { if (!transform) return; @@ -113,50 +157,23 @@ static void _buildTransform(jerry_value_t context, float frameNo, LottieTransfor auto obj = jerry_object(); jerry_object_set_sz(context, "transform", obj); - { - auto anchorPoint = jerry_object(); - auto value = transform->anchor(frameNo); - auto val1 = jerry_number(value.x); - auto val2 = jerry_number(value.y); - jerry_object_set_index(anchorPoint, 0, val1); - jerry_object_set_index(anchorPoint, 1, val2); - jerry_object_set_sz(obj, "anchorPoint", anchorPoint); - jerry_value_free(val1); - jerry_value_free(val2); - jerry_value_free(anchorPoint); - } + auto anchorPoint = _value(frameNo, &transform->anchor); + jerry_object_set_sz(obj, "anchorPoint", anchorPoint); + jerry_value_free(anchorPoint); - { - auto position = jerry_object(); - auto value = transform->position(frameNo); - auto val1 = jerry_number(value.x); - auto val2 = jerry_number(value.y); - jerry_object_set_index(position, 0, val1); - jerry_object_set_index(position, 1, val2); - jerry_object_set_sz(obj, "position", position); - jerry_value_free(val1); - jerry_value_free(val2); - jerry_value_free(position); - } + auto position = _value(frameNo, &transform->position); + jerry_object_set_sz(obj, "position", position); + jerry_value_free(position); - { - auto scale = jerry_object(); - auto value = transform->scale(frameNo); - auto val1 = jerry_number(value.x); - auto val2 = jerry_number(value.y); - jerry_object_set_index(scale, 0, val1); - jerry_object_set_index(scale, 1, val2); - jerry_object_set_sz(obj, "scale", scale); - jerry_value_free(val1); - jerry_value_free(val2); - jerry_value_free(scale); - } + auto scale = _value(frameNo, &transform->scale); + jerry_object_set_sz(obj, "scale", scale); + jerry_value_free(scale); - auto rotation = jerry_number(transform->rotation(frameNo)); + auto rotation = _value(frameNo, &transform->rotation); jerry_object_set_sz(obj, "rotation", rotation); jerry_value_free(rotation); - auto opacity = jerry_number(transform->opacity(frameNo)); + auto opacity = _value(frameNo, &transform->opacity); jerry_object_set_sz(obj, "opacity", opacity); jerry_value_free(opacity); @@ -315,50 +332,6 @@ static void _buildLayer(jerry_value_t context, float frameNo, LottieLayer* layer } -static jerry_value_t _value(float frameNo, LottieExpression* exp) -{ - switch (exp->property->type) { - case LottieProperty::Type::Point: { - auto value = jerry_object(); - auto pos = (*static_cast(exp->property))(frameNo); - auto val1 = jerry_number(pos.x); - auto val2 = jerry_number(pos.y); - jerry_object_set_index(value, 0, val1); - jerry_object_set_index(value, 1, val2); - jerry_value_free(val1); - jerry_value_free(val2); - return value; - } - case LottieProperty::Type::Float: { - return jerry_number((*static_cast(exp->property))(frameNo)); - } - case LottieProperty::Type::Opacity: { - return jerry_number((*static_cast(exp->property))(frameNo)); - } - case LottieProperty::Type::PathSet: { - auto value = jerry_object(); - jerry_object_set_native_ptr(value, nullptr, exp->property); - return value; - } - case LottieProperty::Type::Position: { - auto value = jerry_object(); - auto pos = (*static_cast(exp->property))(frameNo); - auto val1 = jerry_number(pos.x); - auto val2 = jerry_number(pos.y); - jerry_object_set_index(value, 0, val1); - jerry_object_set_index(value, 1, val2); - jerry_value_free(val1); - jerry_value_free(val2); - return value; - } - default: { - TVGERR("LOTTIE", "Non supported type for value? = %d", (int) exp->property->type); - } - } - return jerry_undefined(); -} - - static jerry_value_t _addsub(const jerry_value_t args[], float addsub) { //1d @@ -636,7 +609,7 @@ 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) { - TVGERR("LOTTIE", "effect is not supported in expressions!"); + TVGLOG("LOTTIE", "effect is not supported in expressions!"); return jerry_undefined(); } @@ -644,7 +617,7 @@ static jerry_value_t _effect(const jerry_call_info_t* info, const jerry_value_t static jerry_value_t _fromCompToSurface(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt) { - TVGERR("LOTTIE", "fromCompToSurface is not supported in expressions!"); + TVGLOG("LOTTIE", "fromCompToSurface is not supported in expressions!"); return jerry_undefined(); } @@ -714,13 +687,40 @@ static jerry_value_t _nearestKey(const jerry_call_info_t* info, const jerry_valu return obj; } +static jerry_value_t _property(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt) +{ + auto data = static_cast(jerry_object_get_native_ptr(info->function, &freeCb)); + auto property = data->obj->property(jerry_value_as_int32(args[0])); + if (!property) return jerry_undefined(); + return _value(data->frameNo, property); +} + + +static jerry_value_t _propertyGroup(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt) +{ + auto data = static_cast(jerry_object_get_native_ptr(info->function, &freeCb)); + auto level = jerry_value_as_int32(args[0]); + + //intermediate group + if (level == 1) { + auto group = jerry_function_external(_property); + jerry_object_set_native_ptr(group, &freeCb, _expcontent(data->exp, data->frameNo, data->obj)); + jerry_object_set_sz(group, "", group); + return group; + } + + TVGLOG("LOTTIE", "propertyGroup(%d)?", level); + + return jerry_undefined(); +} + static jerry_value_t _valueAtTime(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt) { auto exp = static_cast(jerry_object_get_native_ptr(info->function, nullptr)); auto time = jerry_value_as_number(args[0]); auto frameNo = exp->comp->frameAtTime(time); - return _value(frameNo, exp); + return _value(frameNo, exp->property); } @@ -749,7 +749,7 @@ static jerry_value_t _velocityAtTime(const jerry_call_info_t* info, const jerry_ break; } default: { - TVGERR("LOTTIE", "Non supported type for velocityAtTime?"); + TVGLOG("LOTTIE", "Non supported type for velocityAtTime?"); return jerry_undefined(); } } @@ -793,7 +793,7 @@ static jerry_value_t _speedAtTime(const jerry_call_info_t* info, const jerry_val break; } default: { - TVGERR("LOTTIE", "Non supported type for speedAtTime?"); + TVGLOG("LOTTIE", "Non supported type for speedAtTime?"); return jerry_undefined(); } } @@ -818,7 +818,7 @@ static bool _loopOutCommon(LottieExpression* exp, const jerry_value_t args[], co } if (exp->loop.mode != LottieExpression::LoopMode::OutCycle && exp->loop.mode != LottieExpression::LoopMode::OutPingPong) { - TVGERR("LOTTIE", "Not supported loopOut type = %d", exp->loop.mode); + TVGLOG("LOTTIE", "Not supported loopOut type = %d", exp->loop.mode); return false; } @@ -870,7 +870,7 @@ static bool _loopInCommon(LottieExpression* exp, const jerry_value_t args[], con } if (exp->loop.mode != LottieExpression::LoopMode::InCycle && exp->loop.mode != LottieExpression::LoopMode::InPingPong) { - TVGERR("LOTTIE", "Not supported loopIn type = %d", exp->loop.mode); + TVGLOG("LOTTIE", "Not supported loopIn type = %d", exp->loop.mode); return false; } @@ -913,7 +913,7 @@ static jerry_value_t _key(const jerry_call_info_t* info, const jerry_value_t arg auto key = jerry_value_as_int32(args[0]); auto frameNo = exp->property->frameNo(key); auto time = jerry_number(exp->comp->timeAtFrame(frameNo)); - auto value = _value(frameNo, exp); + auto value = _value(frameNo, exp->property); auto obj = jerry_object(); jerry_object_set_sz(obj, EXP_TIME, time); @@ -993,7 +993,7 @@ static void _buildPath(jerry_value_t context, LottieExpression* exp) static void _buildProperty(float frameNo, jerry_value_t context, LottieExpression* exp) { - auto value = _value(frameNo, exp); + auto value = _value(frameNo, exp->property); jerry_object_set_sz(context, EXP_VALUE, value); jerry_value_free(value); @@ -1060,8 +1060,13 @@ static void _buildProperty(float frameNo, jerry_value_t context, LottieExpressio jerry_object_set_sz(context, "numKeys", numKeys); jerry_value_free(numKeys); - //propertyGroup(countUp = 1) + auto propertyGroup = jerry_function_external(_propertyGroup); + jerry_object_set_native_ptr(propertyGroup, &freeCb, _expcontent(exp, frameNo, exp->object)); + jerry_object_set_sz(context, "propertyGroup", propertyGroup); + jerry_value_free(propertyGroup); + //propertyIndex + //name //content("name"), #look for the named property from a layer @@ -1069,6 +1074,9 @@ static void _buildProperty(float frameNo, jerry_value_t context, LottieExpressio jerry_object_set_sz(context, EXP_CONTENT, content); jerry_object_set_native_ptr(content, &freeCb, _expcontent(exp, frameNo, exp->layer)); jerry_value_free(content); + + //expansions per types + if (exp->property->type == LottieProperty::Type::PathSet) _buildPath(context, exp); } @@ -1303,13 +1311,17 @@ jerry_value_t LottieExpressions::evaluate(float frameNo, LottieExpression* exp) buildComp(thisComp, frameNo, exp->layer->comp, exp); //update global context values + _buildProperty(frameNo, global, exp); + + //this layer jerry_object_set_native_ptr(thisLayer, nullptr, exp->layer); _buildLayer(thisLayer, frameNo, exp->layer, exp->comp->root, exp); + //this property jerry_object_set_native_ptr(thisProperty, nullptr, exp->property); - _buildProperty(frameNo, global, exp); + _buildProperty(frameNo, thisProperty, exp); - if (exp->property->type == LottieProperty::Type::PathSet) _buildPath(thisProperty, exp); + //expansions per object type if (exp->object->type == LottieObject::Transform) _buildTransform(global, frameNo, static_cast(exp->object)); //evaluate the code diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index 448042b7..82612d8c 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -119,6 +119,7 @@ struct LottieObject } virtual bool mergeable() { return false; } + virtual LottieProperty* property(uint16_t ix) { return nullptr; } unsigned long id = 0; Type type; @@ -345,6 +346,13 @@ struct LottieEllipse : LottieShape LottieShape::prepare(LottieObject::Ellipse); } + LottieProperty* property(uint16_t ix) override + { + if (position.ix == ix) return &position; + if (size.ix == ix) return &size; + return nullptr; + } + LottiePosition position = Point{0.0f, 0.0f}; LottiePoint size = Point{0.0f, 0.0f}; }; diff --git a/src/loaders/lottie/tvgLottieParser.cpp b/src/loaders/lottie/tvgLottieParser.cpp index 919e28d6..6edf9661 100644 --- a/src/loaders/lottie/tvgLottieParser.cpp +++ b/src/loaders/lottie/tvgLottieParser.cpp @@ -513,6 +513,8 @@ void LottieParser::parseProperty(T& prop, LottieObject* obj) comp->slots.push(new LottieSlot(sid, obj, type)); } else if (KEY_AS("x")) { prop.exp = _expression(getStringCopy(), comp, context.layer, context.parent, &prop); + } else if (KEY_AS("ix")) { + prop.ix = getInt(); } else skip(key); } prop.type = type; diff --git a/src/loaders/lottie/tvgLottieProperty.h b/src/loaders/lottie/tvgLottieProperty.h index b191669b..54388597 100644 --- a/src/loaders/lottie/tvgLottieProperty.h +++ b/src/loaders/lottie/tvgLottieProperty.h @@ -181,10 +181,10 @@ struct LottieProperty LottieExpression* exp = nullptr; Type type; - - virtual ~LottieProperty() {} + uint8_t ix; //property index //TODO: Apply common bodies? + virtual ~LottieProperty() {} virtual uint32_t frameCnt() = 0; virtual uint32_t nearest(float time) = 0; virtual float frameNo(int32_t key) = 0; @@ -208,7 +208,7 @@ struct LottieExpression float in = FLT_MAX; //looping duration in frame number LoopMode mode = None; } loop; -; + ~LottieExpression() { free(code);