Esempio n. 1
0
def gen_layer_image(lottie, layer, idx):
    """
    Generates the dictionary corresponding to layers/image.json

    Args:
        lottie (dict)               : Lottie generated image stored here
        layer  (lxml.etree._Element): Synfig format image layer
        idx    (int)                : Stores the index(number of) of image layer

    Returns:
        (None)
    """
    group.update_layer(layer)

    lottie["ddd"] = settings.DEFAULT_3D
    lottie["ind"] = idx
    lottie["ty"] = settings.LAYER_IMAGE_TYPE
    set_layer_desc(layer, settings.LAYER_IMAGE_NAME + str(idx), lottie)
    lottie["sr"] = settings.LAYER_DEFAULT_STRETCH
    lottie["ks"] = {}  # Transform properties to be filled

    settings.lottie_format["assets"].append({})
    st = add_image_asset(settings.lottie_format["assets"][-1], layer)
    asset = settings.lottie_format["assets"][-1]

    # setting class (jpg, png)
    lottie["cl"] = asset["p"].split(".")[-1]

    # setting the reference id
    lottie["refId"] = asset["id"]

    pos1_animate = is_animated(st["tl"][0])
    pos2_animate = is_animated(st["br"][0])
    # If pos1 is not animated
    if pos1_animate in {0, 1}:
        st["tl"] = gen_dummy_waypoint(st["tl"], "param", "vector")
    # If pos2 is not animated
    if pos2_animate in {0, 1}:
        st["br"] = gen_dummy_waypoint(st["br"], "param", "vector")

    st["scale"] = gen_image_scale(st["tl"][0], st["br"][0], asset["w"],
                                  asset["h"])

    anchor = settings.DEFAULT_ANCHOR
    rotation = settings.DEFAULT_ROTATION

    # Setting opacity in transform
    for chld in layer:
        if chld.tag == "param" and chld.attrib["name"] == "amount":
            opacity = chld

    gen_helpers_transform(lottie["ks"], layer, st["tl"][0], anchor,
                          st["scale"][0], rotation, opacity[0])

    lottie["ao"] = settings.LAYER_DEFAULT_AUTO_ORIENT

    lottie["ip"] = settings.lottie_format["ip"]
    lottie["op"] = settings.lottie_format["op"]
    lottie["st"] = 0  # Don't know yet
    get_blend(lottie, layer)
Esempio n. 2
0
def gen_shapes_fill(lottie, layer):
    """
    Generates the dictionary corresponding to shapes/fill.json

    Args:
        lottie (dict)               : The lottie generated fill layer will be stored in it
        layer  (lxml.etree._Element): Synfig format fill (can be shape/solid anything, we
                                      only need color and opacity part from it) layer

    Returns:
        (None)
    """
    index = Count()
    lottie["ty"] = "fl"  # Type if fill
    lottie["c"] = {}  # Color
    lottie["o"] = {}  # Opacity of the fill layer
    for child in layer:
        if child.tag == "param":
            if child.attrib["name"] == "color":
                is_animate = is_animated(child[0])
                if is_animate == 2:
                    gen_value_Keyframed(lottie["c"], child[0], index.inc())

                else:
                    if is_animate == 0:
                        val = child[0]
                    else:
                        val = child[0][0][0]
                    red = float(val[0].text)
                    green = float(val[1].text)
                    blue = float(val[2].text)
                    red, green, blue = red ** (1/settings.GAMMA), green **\
                    (1/settings.GAMMA), blue ** (1/ settings.GAMMA)
                    alpha = float(val[3].text)
                    gen_properties_value(lottie["c"],
                                         [red, green, blue, alpha],
                                         index.inc(),
                                         settings.DEFAULT_ANIMATED,
                                         settings.NO_INFO)

            elif child.attrib["name"] == "amount":
                is_animate = is_animated(child[0])
                if is_animate == 2:
                    # Telling the function that this is for opacity
                    child[0].attrib['type'] = 'opacity'
                    gen_value_Keyframed(lottie["o"], child[0], index.inc())

                else:
                    if is_animate == 0:
                        val = float(child[0].attrib["value"]
                                    ) * settings.OPACITY_CONSTANT
                    else:
                        val = float(child[0][0][0].attrib["value"]
                                    ) * settings.OPACITY_CONSTANT
                    gen_properties_value(lottie["o"], val, index.inc(),
                                         settings.DEFAULT_ANIMATED,
                                         settings.NO_INFO)
Esempio n. 3
0
def gen_shapes_fill(lottie, layer):
    """
    Generates the dictionary corresponding to shapes/fill.json

    Args:
        lottie (dict)               : The lottie generated fill layer will be stored in it
        layer  (common.Layer.Layer)  : Synfig format fill (can be shape/solid anything, we
                                    only need color and opacity part from it) layer

    Returns:
        (None)
    """
    index = Count()
    lottie["ty"] = "fl"  # Type if fill
    lottie["c"] = {}  # Color
    lottie["o"] = {}  # Opacity of the fill layer

    # Color
    color = layer.get_param("color").get()
    is_animate = is_animated(color[0])
    if is_animate == settings.ANIMATED:
        gen_value_Keyframed(lottie["c"], color[0], index.inc())

    else:
        if is_animate == settings.NOT_ANIMATED:
            val = color[0]
        else:
            val = color[0][0][0]
        red = float(val[0].text)
        green = float(val[1].text)
        blue = float(val[2].text)
        red, green, blue = red**(1 / settings.GAMMA[0]), green**(
            1 / settings.GAMMA[1]), blue**(1 / settings.GAMMA[2])
        alpha = float(val[3].text)
        gen_properties_value(lottie["c"], [red, green, blue, alpha],
                             index.inc(), settings.DEFAULT_ANIMATED,
                             settings.NO_INFO)

    # Color Opacity
    opacity = layer.get_param("amount").get()
    is_animate = is_animated(opacity[0])
    if is_animate == settings.ANIMATED:
        # Telling the function that this is for opacity
        opacity[0].attrib['type'] = 'opacity'
        gen_value_Keyframed(lottie["o"], opacity[0], index.inc())

    else:
        if is_animate == settings.NOT_ANIMATED:
            val = float(opacity[0].attrib["value"]) * settings.OPACITY_CONSTANT
        else:
            val = float(
                opacity[0][0][0].attrib["value"]) * settings.OPACITY_CONSTANT
        gen_properties_value(lottie["o"], val, index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)
Esempio n. 4
0
def gen_effects_opacity(lottie, layer, idx):
    """
    Generates the dictionary corresponding to effects/opacity.json

    Args:
        lottie (dict)                : Lottie format effects stored in this
        layer  (lxml.etree._Element) : Synfig format layer
        idx    (int)                 : Index/Count of effect

    Returns:
        (None)
    """
    index = Count()
    lottie["ty"] = settings.EFFECTS_OPACITY  # Effect type
    lottie["nm"] = "Opacity"  # Name
    lottie["ix"] = idx  # Index
    lottie["v"] = {}  # Value of opacity
    for child in layer:
        if child.attrib["name"] == "amount":
            is_animate = is_animated(child[0])
            if is_animate == 2:
                # Telling the function that this is for opacity
                child[0].attrib['type'] = 'effects_opacity'
                gen_value_Keyframed(lottie["v"], child[0], index.inc())

            else:
                if is_animate == 0:
                    val = float(child[0].attrib["value"])
                else:
                    val = float(child[0][0][0].attrib["value"])
                gen_properties_value(lottie["v"], val, index.inc(),
                                     settings.DEFAULT_ANIMATED,
                                     settings.NO_INFO)
Esempio n. 5
0
def gen_linear_gradient(lottie, layer, idx):
    """
    Generates the dictionary corresponding to shapes/gFill.json but with linear gradient

    Args:
    """
    index = Count()
    lottie["ty"] = "gf"
    lottie["r"] = 1  # Don't know it's meaning yet, but works without this also
    lottie["o"] = {}  # Opacity of the gradient layer
    lottie["nm"] = layer.get_description()
    lottie["t"] = 1  # 1 means linear gradient layer
    lottie["s"] = {}  # Starting point of gradient
    lottie["e"] = {}  # Ending point of gradient
    lottie["g"] = {}  # Gradient information is stored here

    # Color Opacity
    opacity = layer.get_param("amount").get()
    is_animate = is_animated(opacity[0])
    if is_animate == settings.ANIMATED:
        # Telling the function that this is for opacity
        opacity[0].attrib['type'] = 'opacity'
        gen_value_Keyframed(lottie["o"], opacity[0], index.inc())

    else:
        if is_animate == settings.NOT_ANIMATED:
            val = float(opacity[0].attrib["value"]) * settings.OPACITY_CONSTANT
        else:
            val = float(
                opacity[0][0][0].attrib["value"]) * settings.OPACITY_CONSTANT
        gen_properties_value(lottie["o"], val, index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)

        # Starting point
        p1 = layer.get_param("p1")
        p1.animate("vector")
        p1.fill_path(lottie, "s")

        # Ending point
        p2 = layer.get_param("p2")
        p2.animate("vector")
        p2.fill_path(lottie, "e")

        # Gradient colors
        lottie["g"]["k"] = {}
        lottie["g"]["ix"] = index.inc()
        gradient = layer.get_param("gradient")
        modify_gradient(gradient)
        gradient.animate(
            "gradient")  # To find the lottie path of the modified gradient
        lottie["g"]["p"] = len(gradient.get()[0][0][0])
        gradient.fill_path(lottie["g"], "k")
        modify_gradient_according_to_latest_version(lottie["g"]["k"])
Esempio n. 6
0
def gen_dummy_waypoint(non_animated,
                       animated_tag,
                       anim_type,
                       animated_name="anything"):
    """
	Makes a non animated parameter to animated parameter by creating a new dummy
	waypoint with constant animation

	Args:
		non_animated (lxml.etree._Element): Holds the non-animated parameter in Synfig xml format
		animated_tag(str)                : Decides the tag of the animation
		anim_type    (str)                : Decides the animation type

	Returns:
		(lxml.etree._Element) : Updated non-animated parameter, which is now animated
	"""
    is_animate = is_animated(non_animated[0])
    if is_animate == settings.ANIMATED:
        # If already animated, no need to add waypoints
        # Forcibly set it's animation type to the given anim_type :needed in:->
        # properties/shapePropKeyframe.py #31
        non_animated[0].attrib["type"] = anim_type
        return non_animated
    elif is_animate == settings.NOT_ANIMATED:
        st = '<{animated_tag} name="{animated_name}"><animated type="{anim_type}"><waypoint time="0s" before="constant" after="constant"></waypoint></animated></{animated_tag}>'
        st = st.format(anim_type=anim_type,
                       animated_name=animated_name,
                       animated_tag=animated_tag)
        root = etree.fromstring(st)
        root[0][0].append(copy.deepcopy(non_animated[0]))
        non_animated = root
    elif is_animate == settings.SINGLE_WAYPOINT:
        # Forcibly set it's animation type to the given anim_type
        non_animated[0].attrib["type"] = anim_type

        non_animated[0][0].attrib["before"] = non_animated[0][0].attrib[
            "after"] = "constant"

    new_waypoint = copy.deepcopy(non_animated[0][0])
    frame = get_frame(non_animated[0][0])
    frame += 1
    time = frame / settings.lottie_format["fr"]
    time = str(time) + "s"
    new_waypoint.attrib["time"] = time
    non_animated[0].insert(1, new_waypoint)
    return non_animated
Esempio n. 7
0
def update_pos(origin):
    """
    Updates the position of parameter in Synfig format

    Args:
        origin (lxml.etree._Element) : Stores the position of element

    Returns:
        (None)
    """
    offset = get_offset()
    is_animate = is_animated(origin[0])
    if is_animate == 0:
        add(origin[0], offset)
    else:
        for waypoint in origin[0]:
            add(waypoint[0], offset)
Esempio n. 8
0
def update_frame_window(node, window):
    """
    Given an animation, finds the minimum and maximum frame at which the
    waypoints are located

    Args:
        node    (lxml.etree._Element) : Animation to be searched in
        window  (dict)                : max and min frame will be stored in this

    Returns:
        (None)
    """
    if is_animated(node) == 2:
        for waypoint in node:
            fr = get_frame(waypoint)
            if fr > window["last"]:
                window["last"] = fr
            if fr < window["first"]:
                window["first"] = fr
Esempio n. 9
0
def get_animated_time_list(child, time_list):
    """
	Appends all the frames corresponding to the waypoints in the
	animated(child[0]) list, in time_list

	Args:
		child     (lxml.etree._Element) : Parent Element of animation
		time_list (set)                 : Will store all the frames at which waypoints are present

	Returns:
		(None)
	"""
    animated = child[0]
    is_animate = is_animated(animated)
    if is_animate in {settings.NOT_ANIMATED, settings.SINGLE_WAYPOINT}:
        return
    for waypoint in animated:
        frame = get_frame(waypoint)
        time_list.add(frame)
Esempio n. 10
0
def gen_effects_color(lottie, layer, idx):
    """
    Generates the dictionary corresponding to effects/color.json

    Args:
        lottie (dict)                : Lottie format effects stored in this
        layer  (lxml.etree._Element) : Synfig format layer
        idx    (int)                 : Index/Count of effect

    Returns:
        (None)

    """
    index = Count()
    lottie["ty"] = settings.EFFECTS_COLOR  # Effect type
    lottie["nm"] = "Color"  # Name
    lottie["ix"] = idx  # Index
    lottie["v"] = {}  # Value of color
    for child in layer:
        if child.tag == "param":
            if child.attrib["name"] == "color":
                is_animate = is_animated(child[0])
                if is_animate == 2:
                    gen_value_Keyframed(lottie["v"], child[0], index.inc())

                else:
                    if is_animate == 0:
                        val = child[0]
                    else:
                        val = child[0][0][0]
                    red = float(val[0].text)
                    green = float(val[1].text)
                    blue = float(val[2].text)
                    red, green, blue = red ** (1/settings.GAMMA), green **\
                    (1/settings.GAMMA), blue ** (1/ settings.GAMMA)
                    alpha = float(val[3].text)
                    gen_properties_value(lottie["v"],
                                         [red, green, blue, alpha],
                                         index.inc(),
                                         settings.DEFAULT_ANIMATED,
                                         settings.NO_INFO)
Esempio n. 11
0
def blurriness(lottie, parameter, idx, direction):
    """
	This function will be called for blur layer direction to create the blurriness
	value dictionary

	Args:
		lottie    (dict)               : Lottie Dictionary for blurriness
		parameter (common.Param.Param) : Synfig format param for blur size
		idx       (int)                : Stores the index(number of) of blurriness
		direction (string)             : Indicates the direction of blurring

	Returns:
		(None)
	"""
    lottie["ty"] = 0
    lottie["nm"] = "Blurriness"
    lottie["mn"] = "Gaussian Blur 1"
    lottie["ix"] = idx
    lottie["v"] = {}
    is_animate = is_animated(parameter[0])
    if is_animate == settings.ANIMATED:
        if direction == "horizontal":
            parameter[0].attrib['type'] = 'blur_anim_x'
            gen_value_Keyframed(lottie["v"], parameter[0], 1)
        else:
            parameter[0].attrib['type'] = 'blur_anim_y'
            gen_value_Keyframed(lottie["v"], parameter[0], 1)
    else:
        if is_animate == settings.NOT_ANIMATED:
            if direction == "horizontal":
                val = float(parameter[0][0].text) * 100
            else:
                val = float(parameter[0][1].text) * 100
        else:
            if direction == "horizontal":
                val = float(parameter[0][0][0].text) * 100
            else:
                val = float(parameter[0][0][1].text) * 100
        gen_properties_value(lottie["v"], val, 1, settings.DEFAULT_ANIMATED,
                             settings.NO_INFO)
Esempio n. 12
0
def gen_radial_gradient(lottie, layer, idx):
    """
    Generates the dictionary correspnding to shapes/gFill.json but with radial gradient

    Args:
    """
    index = Count()
    lottie["ty"] = "gf"
    lottie["r"] = 1  # Don't know it's meaning yet, but works without this also
    lottie["o"] = {}  # Opacity of the gradient layer
    lottie["nm"] = layer.get_description()
    lottie["t"] = 2  # 2 means radial gradient layer
    lottie["s"] = {}  # Starting point of gradient
    lottie["e"] = {}  # Ending point of gradient
    lottie["g"] = {}  # Gradient information is stored here

    # Color Opacity
    opacity = layer.get_param("amount").get()
    is_animate = is_animated(opacity[0])
    if is_animate == settings.ANIMATED:
        # Telling the function that this is for opacity
        opacity[0].attrib['type'] = 'opacity'
        gen_value_Keyframed(lottie["o"], opacity[0], index.inc())

    else:
        if is_animate == settings.NOT_ANIMATED:
            val = float(opacity[0].attrib["value"]) * settings.OPACITY_CONSTANT
        else:
            val = float(
                opacity[0][0][0].attrib["value"]) * settings.OPACITY_CONSTANT
        gen_properties_value(lottie["o"], val, index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)

        # Gradient colors
        lottie["g"]["k"] = {}
        lottie["g"]["ix"] = index.inc()
        gradient = layer.get_param("gradient")
        modify_gradient(gradient)
        gradient.animate(
            "gradient")  # To find the lottie path of the modified gradient
        lottie["g"]["p"] = len(gradient.get()[0][0][0])
        gradient.fill_path(lottie["g"], "k")
        modify_gradient_according_to_latest_version(lottie["g"]["k"])

        # Starting point and Ending points need to be retrieved from center and radius
        center = layer.get_param("center")
        center.animate("vector")
        center.fill_path(lottie, "s")

        radius = layer.get_param("radius")
        radius.animate("real")

        # Ending point will be (start[0] + radius, start[1])
        # Below is just a modification of fill_path function
        expression = "var $bm_rt; $bm_rt = {expr}"
        x_expr = "sum(" + center.expression + "[0], " + radius.expression + ")"
        y_expr = center.expression + "[1]"
        expr = "[" + x_expr + ", " + y_expr + "]"
        expression = expression.format(expr=expr)
        gen_properties_value(lottie["e"], [1, 1], 0, 0, expression)
        if "ef" not in center.get_layer().get_lottie_layer().keys():
            center.get_layer().get_lottie_layer()["ef"] = []
        # If center has any expression controllers, then they would have been pushed earlier by fill_path, hence no need
        # center.get_layer().get_lottie_layer()["ef"].extend(center.expression_controllers)
        center.get_layer().get_lottie_layer()["ef"].extend(
            radius.expression_controllers)
Esempio n. 13
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)
Esempio n. 14
0
def gen_bline_outline_constant(lottie, bline_point, layer, transformation, idx):
	"""
	"""
	index = Count()
	lottie["ty"]  = "gr"
	lottie["nm"]  = "Shape "+ str(idx)
	lottie["np"]  = 3
	lottie["cix"] = 2
	lottie["bm"]  = 0
	lottie["ix"]  = idx
	lottie["mn"]  = "ADBE Vector Group " +str(idx)
	lottie["hd"]  = "false"
	lottie["it"]  = []
	lottie["it"].append({})
	lottie["it"].append({})
	lottie["it"].append({})

	bline = Bline(bline_point[0], bline_point)

	#Creating transformation dictionary
	lottie["it"][2]["ty"] = "tr"
	lottie["it"][2]["nm"] = "Transform"
	lottie["it"][2].update(transformation)
	#Creating stroke dictionary
	lottie["it"][1]["ty"] = "st"
	lottie["it"][1]["lc"] = 2
	lottie["it"][1]["lj"] = 1
	lottie["it"][1]["ml"] = 37
	lottie["it"][1]["bm"] = 0
	lottie["it"][1]["nm"] = "Stroke " + str(idx)
	lottie["it"][1]["mn"] = "ADBE Vector Graphic - Stroke " +str(idx)
	lottie["it"][1]["hd"] = "false"
	lottie["it"][1]["c"]  = {}
	lottie["it"][1]["o"]  = {}
	lottie["it"][1]["w"]  = {}

	#Color
	color = layer.get_param("color").get()
	is_animate = is_animated(color[0])
	if is_animate == settings.ANIMATED:
		gen_value_Keyframed(lottie["it"][1]["c"], color[0], index.inc())

	else:
		if is_animate == settings.NOT_ANIMATED:
			val = color[0]
		else:
			val = color[0][0][0]
		red = float(val[0].text)
		green = float(val[1].text)
		blue = float(val[2].text)
		red, green, blue = red ** (1/settings.GAMMA[0]), green ** (1/settings.GAMMA[1]), blue ** (1/ settings.GAMMA[2])
		alpha = float(val[3].text)
		gen_properties_value(lottie["it"][1]["c"],
							[red, green, blue, alpha],
							index.inc(),
							settings.DEFAULT_ANIMATED,
							settings.NO_INFO)

	#Opacity
	opacity = layer.get_param("amount")
	opacity.animate("opacity")
	opacity.fill_path(lottie["it"][1],"o")

	#Constant width
	loop = bline.get_loop()
	width = layer.get_param("width")
	width.scale_convert_link(1)
	width.animate("real")
	width.fill_path(lottie["it"][1],"w")

	#Creating shape dictionary
	lottie["it"][0]["ind"] =  0
	lottie["it"][0]["ty"] = "sh"
	lottie["it"][0]["ix"] = 1
	lottie["it"][0]["ks"] = {}
	lottie["it"][0]["nm"] =  "Path 1"
	lottie["it"][0]["mn"] =  "ADBE Vector Shape - Group"
	lottie["it"][0]["hd"] =  "false"
	lottie["it"][0]["ks"]["a"] = 1 
	lottie["it"][0]["ks"]["ix"] = lottie["it"][0]["ix"] + 1 
	lottie["it"][0]["ks"]["k"] = []

	window = {}
	window["first"] = sys.maxsize
	window["last"] = -1

	for entry in bline.get_entry_list():
		pos = entry["point"]
		width = entry["width"]
		t1 = entry["t1"]
		t2 = entry["t2"]
		split_r = entry["split_radius"]
		split_a = entry["split_angle"]

		pos.update_frame_window(window)
		# Empty the pos and fill in the new animated pos
		pos.animate("vector")

		width.update_frame_window(window)
		width.animate("real")

		split_r.update_frame_window(window)
		split_r.animate_without_path("bool")

		split_a.update_frame_window(window)
		split_a.animate_without_path("bool")

		animate_tangents(t1, window)
		animate_tangents(t2, window)


	outer_width = layer.get_param("width")
	sharp_cusps = layer.get_param("sharp_cusps")
	expand = layer.get_param("expand")
	r_tip0 = layer.get_param("round_tip[0]")
	r_tip1 = layer.get_param("round_tip[1]")
	homo_width = layer.get_param("homogeneous_width")
	origin = layer.get_param("origin")

	# Animating the origin
	origin.update_frame_window(window)
	origin.animate("vector")

	# Animating the outer width
	outer_width.update_frame_window(window)
	outer_width.animate("real")

	# Animating the sharp_cusps
	sharp_cusps.update_frame_window(window)
	sharp_cusps.animate_without_path("bool")

	# Animating the expand param
	expand.update_frame_window(window)
	expand.animate("real")

	# Animating the round tip 0
	r_tip0.update_frame_window(window)
	r_tip0.animate_without_path("bool")

	# Animating the round tip 1
	r_tip1.update_frame_window(window)
	r_tip1.animate_without_path("bool")

	# Animating the homogeneous width
	homo_width.update_frame_window(window)
	homo_width.animate_without_path("bool")
	# Minimizing the window size
	if window["first"] == sys.maxsize and window["last"] == -1:
		window["first"] = window["last"] = 0
	
	frames = list(set(settings.WAYPOINTS_LIST))
	length = bline.get_len()

	flag = False
	if loop:
		flag = True

	for fr in frames:
		if fr!=1:
			st_val = insert_dict_at(lottie["it"][0]["ks"]["k"], -1, fr, flag,True)
			cur_origin = origin.get_value(fr)
			for point in range(0,length):
				pos_ret, width, t1, t2, split_r_val, split_a_val = get_outline_param_at_frame(bline[point],fr)
				cubic_to(pos_ret,t1,t2,st_val,cur_origin,False,True)
Esempio n. 15
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
Esempio n. 16
0
def gen_shapes_rectangle(lottie, layer, idx):
    """
    Generates the dictionary corresponding to shapes/rect.json

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

    Returns:
        (None)
    """
    index = Count()
    lottie["ty"] = "rc"  # Type: rectangle
    lottie["p"] = {}  # Position of rectangle
    lottie["d"] = settings.DEFAULT_DIRECTION
    lottie["s"] = {}  # Size of rectangle
    lottie["ix"] = idx  # setting the index
    lottie["r"] = {}  # Rounded corners of rectangle
    points = {}
    bevel_found = False
    expand_found = False  # For filled rectangle layers

    for child in layer:
        if child.tag == "param":
            if child.attrib["name"] == "point1":
                points["1"] = child  # Store address of child here

            elif child.attrib["name"] == "point2":
                points["2"] = child  # Store address of child here

            elif child.attrib["name"] == "expand":
                expand_found = True
                param_expand = child

            elif child.attrib["name"] == "bevel":
                bevel_found = True
                is_animate = is_animated(child[0])
                if is_animate == 2:
                    gen_value_Keyframed(lottie["r"], child[0], index.inc())
                else:
                    bevel = get_child_value(is_animate, child, "value")
                    bevel *= settings.PIX_PER_UNIT
                    gen_properties_value(lottie["r"], bevel, index.inc(),
                                         settings.DEFAULT_ANIMATED,
                                         settings.NO_INFO)
    if not bevel_found:  # For rectangle layer in stable version 1.2.2
        bevel = 0
        gen_properties_value(lottie["r"], bevel, index.inc(),
                             settings.DEFAULT_ANIMATED, settings.NO_INFO)

    if not expand_found:  # Means filled rectangle layer, gen expand param
        st = "<param name='expand'><real value='0.0'/></param>"
        param_expand = etree.fromstring(st)

    # If expand parameter is not animated
    param_expand = gen_dummy_waypoint(param_expand, "param", "real")

    # expand parameter needs to be positive: required by Synfig
    make_positive_valued(param_expand)

    # If p1 not animated
    points["1"] = gen_dummy_waypoint(points["1"], "param", "vector")

    # If p2 not animated
    points["2"] = gen_dummy_waypoint(points["2"], "param", "vector")

    both_points_animated(points["1"], points["2"], param_expand, lottie, index)
Esempio n. 17
0
def gen_layer_shape_solid(lottie, layer, idx):
    """
    Generates the dictionary corresponding to layers/shapes.json

    Args:
        lottie (dict)               : Lottie generated solid layer stored here
        layer  (lxml.etree._Element): Synfig format solid layer
        idx    (int)                : Stores the index(number of) of solid layer

    Returns:
        (None)
    """
    update_layer(layer)

    # Setting the solid layer which will be masked
    index = Count()
    lottie["ddd"] = settings.DEFAULT_3D
    lottie["ind"] = idx
    lottie["ty"] = settings.LAYER_SOLID_TYPE
    set_layer_desc(layer, settings.LAYER_SOLID_NAME + str(idx), lottie)
    lottie["sr"] = settings.LAYER_DEFAULT_STRETCH
    lottie["ks"] = {}  # Transform properties to be filled
    lottie["ef"] = []  # Stores the effects

    pos = [
        settings.lottie_format["w"] / 2 + get_additional_width() / 2,
        settings.lottie_format["h"] / 2 + get_additional_height() / 2
    ]
    anchor = pos
    gen_helpers_transform(lottie["ks"], layer, pos, anchor)

    lottie["ef"].append({})
    gen_effects_fill(lottie["ef"][-1], layer, index.inc())

    lottie["ao"] = settings.LAYER_DEFAULT_AUTO_ORIENT
    lottie["sw"] = settings.lottie_format["w"] + get_additional_width(
    )  # Solid Width
    lottie["sh"] = settings.lottie_format["h"] + get_additional_height(
    )  # Solid Height

    invert = False
    for chld in layer:
        if chld.tag == "param":
            if chld.attrib["name"] == "color":
                lottie["sc"] = get_color_hex(chld[0])  # Solid Color
            elif chld.attrib["name"] == "invert":
                is_animate = is_animated(chld[0])
                if is_animate == 0:
                    val = chld[0].attrib["value"]
                elif is_animate == 1:
                    val = chld[0][0][0].attrib["value"]
                else:
                    # If animated, always set invert to false
                    val = "false"
                if val == "true":
                    invert = True
            elif chld.attrib["name"] in {"bline", "vector_list"}:
                bline_point = chld[0]

    lottie["ip"] = settings.lottie_format["ip"]
    lottie["op"] = settings.lottie_format["op"]
    lottie["st"] = 0  # Don't know yet
    get_blend(lottie, layer)

    hasMask = True

    lottie["hasMask"] = hasMask
    lottie["masksProperties"] = []
    lottie["masksProperties"].append({})

    if layer.attrib["type"] in {
            "star", "circle", "rectangle", "filled_rectangle"
    }:
        bline_point = layer

    gen_mask(lottie["masksProperties"][0], invert, bline_point, index.inc())
Esempio n. 18
0
def gen_layer_shape_solid(lottie, layer, idx):
    """
    Generates the dictionary corresponding to layers/shapes.json

    Args:
        lottie (dict)       : Lottie generated solid layer stored here
        layer  (common.Layer.Layer) : Synfig format solid layer
        idx    (int)        : Stores the index(number of) of solid layer

    Returns:
        (None)
    """
    layer.add_offset()

    # Setting the solid layer which will be masked
    index = Count()
    lottie["ddd"] = settings.DEFAULT_3D
    lottie["ind"] = idx
    lottie["ty"] = settings.LAYER_SOLID_TYPE
    lottie["nm"] = layer.get_description()
    lottie["sr"] = settings.LAYER_DEFAULT_STRETCH
    lottie["ks"] = {}  # Transform properties to be filled
    lottie["ef"] = []  # Stores the effects

    pos = [
        settings.lottie_format["w"] / 2 + get_additional_width() / 2,
        settings.lottie_format["h"] / 2 + get_additional_height() / 2
    ]
    anchor = pos
    gen_helpers_transform(lottie["ks"], pos, anchor)

    lottie["ef"].append({})
    gen_effects_fill(lottie["ef"][-1], layer, index.inc())

    lottie["ao"] = settings.LAYER_DEFAULT_AUTO_ORIENT
    lottie["sw"] = settings.lottie_format["w"] + get_additional_width(
    )  # Solid Width
    lottie["sh"] = settings.lottie_format["h"] + get_additional_height(
    )  # Solid Height

    lottie["sc"] = get_color_hex(layer.get_param("color").get()[0])

    invert = False
    Inv = layer.get_param("invert").get()
    flag = False
    #So far only 'not' convert method seems to be supported for invert param in circle, will add more subsequently.
    if Inv is not None:
        if "bool" not in str(Inv[0]) and "animated" not in str(Inv[0]):
            is_animate = is_animated(Inv[0][0][0])
            flag = True
        else:
            is_animate = is_animated(Inv[0])
        if is_animate == settings.NOT_ANIMATED:
            if flag:
                val = "false"
                if Inv[0][0][0].attrib["value"] == "false":
                    val = "true"
            else:
                val = Inv[0].attrib["value"]
        elif is_animate == settings.SINGLE_WAYPOINT:
            if flag:
                val = "false"
                if Inv[0][0][0][0][0].attrib["value"] == "false":
                    val = "true"
            else:
                val = Inv[0][0][0].attrib["value"]
        else:
            # If animated, always set invert to false
            val = "false"
        if val == "true":
            invert = True

    lottie["ip"] = settings.lottie_format["ip"]
    lottie["op"] = settings.lottie_format["op"]
    lottie["st"] = 0  # Don't know yet
    get_blend(lottie, layer)

    hasMask = True

    lottie["hasMask"] = hasMask
    lottie["masksProperties"] = []
    lottie["masksProperties"].append({})

    if layer.get_type() in {"star", "circle", "rectangle", "filled_rectangle"}:
        bline_point = layer
    else:
        bline_point = layer.get_param("bline", "vector_list")

    gen_mask(lottie["masksProperties"][0], invert, bline_point, index.inc())
Esempio n. 19
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)