Exemple #1
0
def cubic_to(vec,
             tan1,
             tan2,
             lottie,
             origin_cur,
             is_rectangle=False,
             constant_width=False):
    """
    Will have to manipulate the tangents here, but they are not managed as tan1
    and tan2 both are zero always

    Args:
        vec (common.Vector.Vector) : position of the point
        tan1 (common.Vector.Vector) : tangent 1 of the point
        tan2 (common.Vector.Vector) : tangent 2 of the point
        lottie (dict) : Final position and tangents will be stored here
        origin_cur (list) : value of the origin at specific frame

    Returns:
        (None)
    """
    vec *= settings.PIX_PER_UNIT
    tan1 *= settings.PIX_PER_UNIT
    tan2 *= settings.PIX_PER_UNIT
    if constant_width:
        tan1, tan2 = convert_tangent_to_lottie(tan1, tan2)
    else:
        tan1, tan2 = convert_tangent_to_lottie(3 * tan1, 3 * tan2)
    pos = change_axis(vec[0], vec[1], not is_rectangle)
    for i in range(len(pos)):
        pos[i] += origin_cur[i]
    lottie["i"].append(tan1.get_list())
    lottie["o"].append(tan2.get_list())
    lottie["v"].append(pos)
Exemple #2
0
def move_to(vec, lottie, origin_cur):
    """
    Don't have to manipulate the tangents because all of them are zero here

    Args:
        vec (common.Vector.Vector) : position of the point
        lottie (dict) : Final position and tangents will be stored here
        origin_cur (list) : value of the origin at specific frame

    Returns:
        (None)
    """
    vec *= settings.PIX_PER_UNIT
    lottie["i"].append([0, 0])
    lottie["o"].append([0, 0])
    pos = change_axis(vec[0], vec[1])
    for i in range(len(pos)):
        pos[i] += origin_cur[i]
    lottie["v"].append(pos)
Exemple #3
0
def gen_helpers_transform(lottie,
                          layer,
                          pos=settings.DEFAULT_POSITION,
                          anchor=settings.DEFAULT_ANCHOR,
                          scale=settings.DEFAULT_SCALE,
                          rotation=settings.DEFAULT_ROTATION,
                          opacity=settings.DEFAULT_OPACITY):
    """
    Generates the dictionary corresponding to helpers/transform.json

    Args:
        lottie (dict)                : Lottie format layer
        layer  (lxml.etree._Element) : Synfig format layer
        pos    (:obj: `list | lxml.etree._Element`, optional) : position of layer
        anchor (:obj: `list | lxml.etree._Element`, optional) : anchor point of layer
        scale (:obj: `list | lxml.etree._Element`, optional) : scale of layer
        rotation (:obj: `float | lxml.etree._Element`, optional) : rotation of layer
        opacity (:obj: `float | lxml.etree._Element`, optional) : Opacity of layer

    Returns:
        (None)
    """
    index = Count()
    lottie["o"] = {}  # opacity/Amount
    lottie["r"] = {}  # Rotation of the layer
    lottie["p"] = {}  # Position of the layer
    lottie["a"] = {}  # Anchor point of the layer
    lottie["s"] = {}  # Scale of the layer

    # setting the position
    if isinstance(pos, list):
        gen_properties_value(lottie["p"], pos, index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)
    else:
        is_animate = is_animated(pos)
        if is_animate == 2:
            gen_properties_multi_dimensional_keyframed(lottie["p"], pos,
                                                       index.inc())
        else:
            x_val, y_val = 0, 0
            if is_animate == 0:
                x_val = float(pos[0].text) * settings.PIX_PER_UNIT
                y_val = float(pos[1].text) * settings.PIX_PER_UNIT
            else:
                x_val = float(pos[0][0][0].text) * settings.PIX_PER_UNIT
                y_val = float(pos[0][0][1].text) * settings.PIX_PER_UNIT
            gen_properties_value(lottie["p"], change_axis(x_val, y_val, True),
                                 index.inc(), settings.DEFAULT_ANIMATED,
                                 settings.NO_INFO)

    # setting the opacity
    if isinstance(opacity, (float, int)):
        gen_properties_value(lottie["o"], opacity, index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)
    else:
        is_animate = is_animated(opacity)
        if is_animate == 2:
            opacity.attrib["type"] = "opacity"
            gen_value_Keyframed(lottie["o"], opacity, index.inc())
        else:
            if is_animate == 0:
                val = float(
                    opacity.attrib["value"]) * settings.OPACITY_CONSTANT
            else:
                val = float(
                    opacity[0][0].attrib["value"]) * settings.OPACITY_CONSTANT
            gen_properties_value(lottie["o"], val, index.inc(),
                                 settings.DEFAULT_ANIMATED, settings.NO_INFO)

    # setting the rotation
    if isinstance(rotation, (float, int)):
        gen_properties_value(lottie["r"], rotation, index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)
    else:
        is_animate = is_animated(rotation)
        if is_animate == 2:
            gen_value_Keyframed(lottie["r"], rotation, index.inc())
        else:
            theta = 0  # default rotation
            if is_animate == 0:
                theta = (float(rotation.attrib["value"]))
            else:
                theta = (float(rotation[0][0].attrib["value"]))
            gen_properties_value(lottie["r"], theta, index.inc(),
                                 settings.DEFAULT_ANIMATED, settings.NO_INFO)

    # setting the anchor point
    if isinstance(anchor, list):
        gen_properties_value(lottie["a"], anchor, index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)
    else:
        is_animate = is_animated(anchor)
        if is_animate == 2:
            gen_properties_multi_dimensional_keyframed(lottie["a"], anchor,
                                                       index.inc())
        else:
            x_val, y_val = 0, 0
            if is_animate == 0:
                x_val = float(anchor[0].text) * settings.PIX_PER_UNIT
                y_val = float(anchor[1].text) * settings.PIX_PER_UNIT
            else:
                x_val = float(anchor[0][0][0].text) * settings.PIX_PER_UNIT
                y_val = float(anchor[0][0][1].text) * settings.PIX_PER_UNIT
            gen_properties_value(lottie["a"], change_axis(x_val, y_val, True),
                                 index.inc(), settings.DEFAULT_ANIMATED,
                                 settings.NO_INFO)

    # setting the scale
    if isinstance(scale, list):
        gen_properties_value(lottie["s"], scale, index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)
    # This means scale parameter is animated
    else:
        is_animate = is_animated(scale)
        if is_animate == 2:
            gen_value_Keyframed(lottie["s"], scale, index.inc())
        else:
            zoom = 0
            if is_animate == 0:
                zoom = float(scale.attrib["value"])
            else:
                zoom = float(scale[0][0].attrib["value"])
            zoom = (math.e**zoom) * 100
            gen_properties_value(lottie["s"], [zoom, zoom], index.inc(),
                                 settings.DEFAULT_ANIMATED, settings.NO_INFO)
Exemple #4
0
def gen_shapes_circle(lottie, layer, idx):
    """
    Generates the dictionary corresponding to shapes/ellipse.json where ellipse
    will always be considered as circle

    Args:
        lottie (dict)               : The lottie generated circle layer will be stored in it
        layer  (lxml.etree._Element): Synfig format circle layer
        idx    (int)                : Stores the index of the circle layer

    Returns:
        (None)
    """
    index = Count()
    lottie["ty"] = "el"  # Type: circle
    lottie["p"] = {}  # Position of circle
    lottie["d"] = settings.DEFAULT_DIRECTION
    lottie["s"] = {}  # Size of circle
    lottie["ix"] = idx  # setting the index

    for child in layer:
        if child.tag == "param":
            if child.attrib["name"] in {"origin", "center"}:
                is_animate = is_animated(child[0])
                if is_animate == 2:
                    gen_properties_multi_dimensional_keyframed(
                        lottie["p"], child[0], index.inc())
                else:
                    x_val, y_val = 0, 0
                    if is_animate == 0:
                        x_val = float(child[0][0].text) * settings.PIX_PER_UNIT
                        y_val = float(child[0][1].text) * settings.PIX_PER_UNIT
                    else:
                        x_val = float(
                            child[0][0][0][0].text) * settings.PIX_PER_UNIT
                        y_val = float(
                            child[0][0][0][1].text) * settings.PIX_PER_UNIT
                    gen_properties_value(lottie["p"],
                                         change_axis(x_val,
                                                     y_val), index.inc(),
                                         settings.DEFAULT_ANIMATED,
                                         settings.NO_INFO)

            # This will be exported as size of ellipse in lottie format
            elif child.attrib["name"] == "radius":
                is_animate = is_animated(child[0])
                if is_animate == 2:
                    child[0].attrib['type'] = "circle_radius"
                    gen_value_Keyframed(lottie["s"], child[0], index.inc())
                else:
                    radius = 0  # default value for radius
                    if is_animate == 0:
                        radius = float(child[0].attrib["value"])
                    else:
                        radius = float(child[0][0][0].attrib["value"])

                    radius_pix = int(settings.PIX_PER_UNIT) * radius
                    diam = radius_pix * 2
                    gen_properties_value(lottie["s"], [diam, diam],
                                         index.inc(),
                                         settings.DEFAULT_ANIMATED,
                                         settings.NO_INFO)
Exemple #5
0
def gen_properties_offset_keyframe(curve_list, animated, i):
    """
    Generates the dictionary corresponding to properties/offsetKeyFrame.json

    Args:
        curve_list (list)                : Stores bezier curve in Lottie format
        animated   (lxml.etree._Element) : Synfig format animation
        i          (int)                 : Iterator for animation

    Returns:
        (TypeError) : If a constant interval is encountered
        (None)      : In all other cases
    """
    lottie = curve_list[-1]

    waypoint, next_waypoint = animated[i], animated[i + 1]
    cur_get_after, next_get_before = waypoint.attrib[
        "after"], next_waypoint.attrib["before"]
    cur_get_before, next_get_after = waypoint.attrib[
        "before"], next_waypoint.attrib["after"]

    # "angle" interpolations never call this function, can be removed by confirming
    if animated.attrib["type"] == "angle":
        if cur_get_after == "auto":
            cur_get_after = "linear"
        if cur_get_before == "auto":
            cur_get_before = "linear"
        if next_get_before == "auto":
            next_get_before = "linear"
        if next_get_after == "auto":
            next_get_after = "linear"

    # Synfig only supports constant interpolations for points
    # "points" never call this function, can be removed by confirming
    if animated.attrib["type"] == "points":
        cur_get_after = "constant"
        cur_get_before = "constant"
        next_get_after = "constant"
        next_get_before = "constant"

    # Calculate positions of waypoints
    cur_pos = parse_position(animated, i)
    next_pos = parse_position(animated, i + 1)

    lottie["i"] = {}  # Time bezier curve, not used in synfig
    lottie["o"] = {}  # Time bezier curve, not used in synfig
    lottie["i"]["x"] = 0.5
    lottie["i"]["y"] = 0.5
    lottie["o"]["x"] = 0.5
    lottie["o"]["y"] = 0.5
    if cur_get_after == "halt":  # For ease out
        ease_out(lottie)
    if next_get_before == "halt":  # For ease in
        ease_in(lottie)
    lottie["t"] = get_frame(waypoint)

    is_transform_axis = False
    if "transform_axis" in animated.keys():
        is_transform_axis = True
    lottie["s"] = change_axis(cur_pos[0], cur_pos[1], is_transform_axis)
    lottie["e"] = change_axis(next_pos[0], next_pos[1], is_transform_axis)
    lottie["to"] = []
    lottie["ti"] = []

    # Calculating the unchanged tangent
    try:
        out_val, in_val = calc_tangent(animated, lottie, i)
    except Exception as excep:
        # This means constant interval
        return excep

    # This module is only needed for origin animation
    lottie["to"] = out_val.get_list()
    lottie["ti"] = in_val.get_list()

    # TCB/!TCB and list is not empty
    if cur_get_before == "auto" and cur_get_after != "auto" and i > 0:
        curve_list[-2]["ti"] = copy.deepcopy(lottie["to"])
        curve_list[-2]["ti"] = [
            -item / settings.TANGENT_FACTOR for item in curve_list[-2]["ti"]
        ]
        curve_list[-2]["ti"][1] = -curve_list[-2]["ti"][1]
        if cur_get_after == "halt":
            curve_list[-2]["i"]["x"] = settings.IN_TANGENT_X
            curve_list[-2]["i"]["y"] = settings.IN_TANGENT_Y

    # Lottie tangent length is larger than synfig
    lottie["ti"] = [item / settings.TANGENT_FACTOR for item in lottie["ti"]]
    lottie["to"] = [item / settings.TANGENT_FACTOR for item in lottie["to"]]

    # Lottie and synfig use different tangents SEE DOCUMENTATION
    lottie["ti"] = [-item for item in lottie["ti"]]

    # IMPORTANT to and ti have to be relative
    # The y-axis is different in lottie
    lottie["ti"][1] = -lottie["ti"][1]
    lottie["to"][1] = -lottie["to"][1]

    # These tangents will be used in actual calculation of points according to
    # Synfig
    lottie["synfig_to"] = [tangent for tangent in lottie["to"]]
    lottie["synfig_ti"] = [-tangent for tangent in lottie["ti"]]
    if cur_get_after == "halt":
        lottie["synfig_to"] = [0 for val in lottie["synfig_to"]]
    if next_get_before == "halt":
        lottie["synfig_ti"] = [0 for val in lottie["synfig_ti"]]
Exemple #6
0
def gen_shapes_star(lottie, layer, idx):
    """
    Generates the dictionary corresponding to shapes/star.json

    Args:
        lottie (dict)               : The lottie generated star layer will be stored in it
        layer  (common.Layer.Layer)  : Synfig format star layer
        idx    (int)                : Stores the index of the star layer

    Returns:
        (None)
    """
    index = Count()
    lottie["ty"] = "sr"  # Type: star
    lottie["pt"] = {}  # Number of points on the star
    lottie["p"] = {}  # Position of star
    lottie["r"] = {}  # Angle / Star's rotation
    lottie["ir"] = {}  # Inner radius
    lottie["or"] = {}  # Outer radius
    lottie["is"] = {}  # Inner roundness of the star
    lottie["os"] = {}  # Outer roundness of the star
    regular_polygon = {"prop": "false"}

    # Regular polygon
    rp = layer.get_param("regular_polygon").get()
    is_animate = is_animated(rp[0])
    if is_animate == 2:
        regular_polygon["prop"] = "changing"
        regular_polygon["animated"] = rp[0]
    elif is_animate == 1:
        regular_polygon["prop"] = rp[0][0][0].attrib["value"]
    else:
        regular_polygon["prop"] = rp[0].attrib["value"]
    regular_polygon["animate"] = is_animate

    # Points
    points = layer.get_param("points").get()
    is_animate = is_animated(points[0])
    if is_animate == 2:
        # To uniquely identify the points, attribute type is changed
        points[0].attrib['type'] = 'points'
        gen_value_Keyframed(lottie["pt"], points[0], index.inc())
    else:
        num_points = 3  # default number of points
        if is_animate == 0:
            num_points = int(points[0].attrib["value"])
        else:
            num_points = int(points[0][0][0].attrib["value"])
        gen_properties_value(lottie["pt"], num_points, index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)

    # Angle
    angle = layer.get_param("angle").get()
    is_animate = is_animated(angle[0])
    if is_animate == 2:
        gen_value_Keyframed(lottie["r"], angle[0], index.inc())
    else:
        theta = 0  # default angle for the star
        if is_animate == 0:
            theta = get_angle(float(angle[0].attrib["value"]))
        else:
            theta = get_angle(float(angle[0][0][0].attrib["value"]))
        gen_properties_value(lottie["r"], theta, index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)

    # Radius1
    radius1 = layer.get_param("radius1").get()
    is_animate = is_animated(radius1[0])
    if is_animate == 2:
        gen_value_Keyframed(lottie["or"], radius1[0], index.inc())
    else:
        r_outer = 0  # default value for outer radius
        if is_animate == 0:
            r_outer = float(radius1[0].attrib["value"])
        else:
            r_outer = float(radius1[0][0][0].attrib["value"])
        gen_properties_value(lottie["or"],
                             int(settings.PIX_PER_UNIT * r_outer), index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)

    # Radius2
    radius2 = layer.get_param("radius2").get()
    is_animate = is_animated(radius2[0])
    if is_animate == 2:
        gen_value_Keyframed(lottie["ir"], radius2[0], index.inc())
    else:
        r_inner = 0  # default value for inner radius
        if is_animate == 0:
            r_inner = float(radius2[0].attrib["value"])
        else:
            r_inner = float(radius2[0][0][0].attrib["value"])
        gen_properties_value(lottie["ir"],
                             int(settings.PIX_PER_UNIT * r_inner), index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)

    # Origin
    origin = layer.get_param("origin").get()
    is_animate = is_animated(origin[0])
    if is_animate == 2:
        gen_properties_multi_dimensional_keyframed(lottie["p"], origin[0],
                                                   index.inc())
    else:
        x_val, y_val = 0, 0
        if is_animate == 0:
            x_val = float(origin[0][0].text) * settings.PIX_PER_UNIT
            y_val = float(origin[0][1].text) * settings.PIX_PER_UNIT
        else:
            x_val = float(origin[0][0][0][0].text) * settings.PIX_PER_UNIT
            y_val = float(origin[0][0][0][1].text) * settings.PIX_PER_UNIT
        gen_properties_value(lottie["p"], change_axis(x_val,
                                                      y_val), index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)

    # If not animated, then go to if, else
    if regular_polygon["animate"] in {0, 1}:
        if regular_polygon["prop"] == "false":
            lottie["sy"] = 1  # Star Type

            # inner property is only needed if type is star
            gen_properties_value(lottie["is"], 0, index.inc(),
                                 settings.DEFAULT_ANIMATED, settings.NO_INFO)
        else:
            lottie["sy"] = 2  # Polygon Type

            # for polygon type, "ir" and "is" must not be present
            del lottie["ir"]

    # If animated, it will always be of type star
    else:
        lottie["sy"] = 1
        gen_properties_value(lottie["is"], 0, index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)

    gen_properties_value(lottie["os"], 0, index.inc(),
                         settings.DEFAULT_ANIMATED, settings.NO_INFO)
    lottie["ix"] = idx