Example #1
0
def get_tangent_at_frame(t1, t2, fr):
    """
    Given a frame, returns the in-tangent and out-tangent at a bline point
    depending on whether split_radius and split_angle is "true"/"false"

    Args:
        t1      (common.Param.Param)  : Holds Tangent 1/In Tangent
        t2      (common.Param.Param)  : Holds Tangent 2/Out Tangent
        split_r (common.Param.Param) : Holds animation of split radius parameter
        split_a (common.Param.Param) : Holds animation of split angle parameter
        fr      (int)                 : Holds the frame value

    Returns:
        (common.Vector.Vector, common.Vector.Vector) : In-tangent and out-tangent at the given frame
    """

    # Setting tangent 1
    r1 = t1.get_subparam("radius").get_value(fr)
    a1 = t1.get_subparam("theta").get_value(fr)

    x, y = radial_to_tangent(r1, a1)
    tangent1 = Vector(x, y)

    # Setting tangent 2
    r2 = t2.get_subparam("radius").get_value(fr)
    a2 = t2.get_subparam("theta").get_value(fr)

    x, y = radial_to_tangent(r2, a2)
    tangent2 = Vector(x, y)

    return tangent1, tangent2
Example #2
0
def get_control_points(interval):
    """
	Returns all 4 control points of a bezier interval

	Args:
		interval (dict) : Holds one interval of the bezier curve that is two waypoints

	Returns:
		(common.Vector.Vector, common.Vector.Vector, common.Vector.Vector, common.Vector.Vector) If the interval holds position bezier
		(float, float, float, float)       Else : the interval holds value bezier
	"""
    # If the interval is for position or vector
    if "to" in interval.keys():
        st = Vector(interval["s"][0], interval["s"][1])
        en = Vector(interval["e"][0], interval["e"][1])
        to = Vector(interval["synfig_to"][0], interval["synfig_to"][1])
        ti = Vector(interval["synfig_ti"][0], interval["synfig_ti"][1])

    # If the interval is for real values
    else:
        st = interval["s"][0]
        en = interval["e"][0]
        to = interval["synfig_o"][0]
        ti = interval["synfig_i"][0]
    return st, to, ti, en
Example #3
0
 def update_tangent2(self):
     if self.tangent_[0].mag_squared() != 0:
         self.tangent2_radius_split_ = Vector(self.tangent_[1].mag(),
                                              self.tangent_[0].angle())
     else:
         self.tangent2_radius_split_ = self.tangent_[1]
     self.tangent2_angle_split_ = Vector(self.tangent_[0].mag(),
                                         self.tangent_[1].angle())
Example #4
0
 def not_on_line_left(self, line_index, point):
     if line_index is len(self.points) - 1:
         point_a = self.points[0]
         point_b = self.points[-1]
     else:
         point_a = self.points[line_index + 1]
         point_b = self.points[line_index]
     line_vector = Vector.by_points_subtraction(point_a, point_b)
     orthogonal_vector = line_vector.orthogonal_vector()
     point_vector = Vector.by_points_subtraction(point, point_b)
     return Vector.dot_product(point_vector, orthogonal_vector) >= 0
Example #5
0
def handle_color():
    """
    Default linear tangent values for color interpolations

    Args:
        (None)

    Returns:
        (misc.Vector, misc.Vector) : out and in tangents for color parameter
    """
    out_val = Vector(0.5, 0.5, "color")
    in_val = Vector(0.5, 0.5, "color")
    return out_val, in_val
Example #6
0
    def get_blinepoint(self, current, t):
        """
        """
        bpcurr = self.get_value_at_frame(self.get_entry_list()[current], t)
        if not bpcurr.get_boned_vertex_flag():
            return bpcurr

        nxt = current
        previous = current

        nxt += 1
        if nxt == self.get_len():
            nxt = 0
        if current == 0:
            previous = self.get_len()
        previous -= 1

        bpprev = self.get_value_at_frame(self.get_entry_list()[previous], t)
        bpnext = self.get_value_at_frame(self.get_entry_list()[nxt], t)

        t1 = bpcurr.get_tangent1()
        t2 = bpcurr.get_tangent2()
        v = bpcurr.get_vertex()
        vp = bpprev.get_vertex()
        vn = bpnext.get_vertex()
        vs = bpcurr.get_vertex_setup()
        vps = bpprev.get_vertex_setup()
        vns = bpnext.get_vertex_setup()
        beta01 = t1.angle()
        beta02 = t2.angle()

        alpha = (vn - vp).angle() - (vns - vps).angle()
        if bpcurr.get_split_tangent_both():
            gamma = ((v - (vn + vp) * 0.5).angle() -
                     (vn - vp).angle()) - ((vs - (vns + vps) * 0.5).angle() -
                                           (vns - vps).angle())
        else:
            gamma = Angle(0)

        beta1 = alpha + gamma + beta01
        beta2 = alpha + gamma + beta02

        tt1 = Vector(t1.mag() * CosAngle(beta1).get(),
                     t1.mag() * SinAngle(beta1).get())
        tt2 = Vector(t2.mag() * CosAngle(beta2).get(),
                     t2.mag() * SinAngle(beta2).get())

        bpcurr.set_tangent1(tt1)
        bpcurr.set_tangent2(tt2)

        return bpcurr
Example #7
0
def get_tangent_at_frame(t1, t2, split_r, split_a, fr):
    """
    Given a frame, returns the in-tangent and out-tangent at a bline point
    depending on whether split_radius and split_angle is "true"/"false"

    Args:
        t1      (common.Param.Param)  : Holds Tangent 1/In Tangent
        t2      (common.Param.Param)  : Holds Tangent 2/Out Tangent
        split_r (common.Param.Param) : Holds animation of split radius parameter
        split_a (common.Param.Param) : Holds animation of split angle parameter
        fr      (int)                 : Holds the frame value

    Returns:
        (common.Vector.Vector, common.Vector.Vector) : In-tangent and out-tangent at the given frame
    """

    # Get value of split_radius and split_angle at frame
    sp_r = split_r.get_value(fr)
    sp_a = split_a.get_value(fr)

    # Setting tangent 1
    r1 = t1.get_subparam("radius").get_value(fr)
    a1 = t1.get_subparam("theta").get_value(fr)

    x, y = radial_to_tangent(r1, a1)
    tangent1 = Vector(x, y)

    # Setting tangent 2
    r2 = t2.get_subparam("radius").get_value(fr)
    a2 = t2.get_subparam("theta").get_value(fr)

    x, y = radial_to_tangent(r2, a2)
    orig_tang2 = Vector(x, y)

    if not sp_r:
        # Use t1's radius
        r2 = r1
    if not sp_a:
        # Use t1's angle
        a2 = a1

    x, y = radial_to_tangent(r2, a2)
    tangent2 = Vector(x, y)

    if sp_r and (not sp_a):
        if tangent1.mag_squared() == 0:
            tangent2 = orig_tang2

    return tangent1, tangent2
Example #8
0
    def radial_interpolation(self, a, b, c):
        """
        """
        if a.is_equal_to(Vector(0, 0)) or b.is_equal_to(Vector(0, 0)):
            return linear_interpolation(a, b, c)

        mag = self.mag_combo(a.mag(), b.mag(), c)
        angle_a = TanAngle(Vector(a[1], a[0]))
        angle_b = TanAngle(Vector(b[1], b[0]))
        diff = DegAngle(angle_b - angle_a).get()
        if diff < -180: angle_b += DegAngle(360)
        elif diff > 180: angle_a += DegAngle(360)
        ang = self.ang_combo(angle_a, angle_b, c)

        return Vector(mag * CosAngle(ang).get(), mag * SinAngle(ang).get())
Example #9
0
def get_tangent_at_frame(t1, t2, split_r, split_a, fr):
    """
    Given a frame, returns the in-tangent and out-tangent at a bline point
    depending on whether split_radius and split_angle is "true"/"false"

    Args:
        t1      (lxml.etree._Element) : Holds Tangent 1/In Tangent
        t2      (lxml.etree._Element) : Holds Tangent 2/Out Tangent
        split_r (lxml.etree._Element) : Holds animation of split radius parameter
        split_a (lxml.etree._Element) : Holds animation of split angle parameter
        fr      (int)                 : Holds the frame value

    Returns:
        (misc.Vector, misc.Vector) : In-tangent and out-tangent at the given frame
    """

    # Get value of split_radius and split_angle at frame
    sp_r = get_bool_at_frame(split_r[0], fr)
    sp_a = get_bool_at_frame(split_a[0], fr)

    # Setting tangent 1
    for chld in t1:
        if chld.tag == "radius_path":
            dictionary = ast.literal_eval(chld.text)
            r1 = get_vector_at_frame(dictionary, fr)
        elif chld.tag == "theta_path":
            dictionary = ast.literal_eval(chld.text)
            a1 = get_vector_at_frame(dictionary, fr)
    x, y = radial_to_tangent(r1, a1)
    tangent1 = Vector(x, y)

    # Setting tangent 2
    for chld in t2:
        if chld.tag == "radius_path":
            dictionary = ast.literal_eval(chld.text)
            r2 = get_vector_at_frame(dictionary, fr)
            if not sp_r:
                # Use t1's radius
                r2 = r1
        elif chld.tag == "theta_path":
            dictionary = ast.literal_eval(chld.text)
            a2 = get_vector_at_frame(dictionary, fr)
            if not sp_a:
                # Use t1's angle
                a2 = a1
    x, y = radial_to_tangent(r2, a2)
    tangent2 = Vector(x, y)
    return tangent1, tangent2
Example #10
0
def clamped_vector(p1, p2, p3, animated, i, lottie, ease):
    """
    Function to generate the collective tangents i.e. x tangent and y tangent
    when clamped waypoints are used

    Args:
        p1       (misc.Vector)         : First point in Co-ordinate System
        p2       (misc.Vector)         : Second point in Co-ordinate System
        p3       (misc.Vector)         : Third point in Co-ordinate System
        animated (lxml.etree._Element) : Synfig format animation
        i        (int)                 : Iterator over animation
        ease     (str)                 : Specifies if it is an ease in animation ease out

    Returns:
        (misc.Vector) : Clamped Vector is returned
    """
    x_tan = clamped_tangent(p1[0], p2[0], p3[0], animated, i)
    y_tan = clamped_tangent(p1[1], p2[1], p3[1], animated, i)

    if isclose(x_tan, 0.0) or isclose(y_tan, 0.0):
        if ease == "in":
            ease_in(lottie)
        else:
            ease_out(lottie)
    return Vector(x_tan, y_tan, animated.attrib["type"])
Example #11
0
def line_intersection(p1, t1, p2, t2):
    """
    This function was adapted from what was
    described on http://www.whisqu.se/per/docs/math28.htm

    Args:
        p1 (common.Vector.Vector) : First point
        t1 (common.Vector.Vector) : First tangent
        p2 (common.Vector.Vector) : Second point
        t2 (common.Vector.Vector) : Second tangent

    Returns:
        (common.Vector.Vector) : intersection of the both the lines
    """
    x0 = p1[0]
    y0 = p1[1]

    x1 = p1[0] + t1[0]
    y1 = p1[1] + t1[1]

    x2 = p2[0]
    y2 = p2[1]

    x3 = p2[0] + t2[0]
    y3 = p2[1] + t2[1]

    near_infinity = 1e+10

    # compute slopes, not the kluge for infinity, however, this will
    # be close enough

    if (x1 - x0) != 0:
        m1 = (y1 - y0) / (x1 - x0)
    else:
        m1 = near_infinity

    if (x3 - x2) != 0:
        m2 = (y3 - y2) / (x3 - x2)
    else:
        m2 = near_infinity

    a1 = m1
    a2 = m2
    b1 = -1.0
    b2 = -1.0
    c1 = y0 - m1*x0
    c2 = y2 - m2*x2

    # compute the inverse of the determinate
    if a1*b2 - a2*b1 == 0:
        det_inv = float('nan')
    else:
        det_inv = 1.0 / (a1*b2 - a2*b1)

    # Use kramer's rule to compute intersection
    return Vector((b1*c2 - b2*c1)*det_inv, (a2*c1 - a1*c2)*det_inv)
Example #12
0
def get_offset():
    """
    Computes the offset by which the layers need to be moved with

    Args:
        (None)
    Returns:
        (common.Vector.Vector) : offset
    """
    x = settings.ADDITIONAL_PRECOMP_WIDTH / 2
    y = settings.ADDITIONAL_PRECOMP_HEIGHT / 2
    offset = Vector(x, -y)
    offset /= settings.PIX_PER_UNIT
    return offset
Example #13
0
    def get_transformed(self, v):
        """
        Rotate or transform a vector using this Matrix

        Args:
            v (common.Vector.Vector) : Vector to be rotated using this matrix

        Returns:
            (common.Vector.Vector) : Rotated vector
        """
        ret = Vector()
        x, y = v[0], v[1]
        ret[0] = x * self.m00 + y * self.m10
        ret[1] = x * self.m01 + y * self.m11
        return ret
Example #14
0
def get_first_control_point(interval):
    """
    Returns the first control point of a bezier interval

    Args:
        interval (dict) : Holds one interval of the bezier curve that is two waypoints

    Returns:
        (misc.Vector) If the interval holds position bezier
        (float)       Else : the interval holds value bezier
    """
    if len(interval["s"]) >= 2:
        st = Vector(interval["s"][0], interval["s"][1])
    else:
        st = interval["s"][0]
    return st
Example #15
0
def get_last_control_point(interval):
    """
	Returns the last control point of a bezier interval

	Args:
		interval (dict) : Holds one interval of the bezier curve that is two waypoints

	Returns:
		(common.Vector.Vector) If the interval holds position bezier
		(float)       Else : the interval holds value bezier
	"""
    if len(interval["e"]) >= 2:
        en = Vector(interval["e"][0], interval["e"][1])
    else:
        en = interval["e"][0]
    return en
Example #16
0
def get_outline_param_at_frame(composite, fr):
    """
    Given a composite and frame, returns the parameters of the outline layer at
    that frame

    Args:
        composite (lxml.etree._Element) : Vertex of outline layer in Synfig format
        fr        (int)                 : frame number

    Returns:
        (misc.Vector) : position of the vertex
        (float)       : width of the vertex
        (misc.Vector) : Tangent 1 of the vertex
        (misc.Vector) : Tangent 2 of the vertex
        (bool)        : True if radius split is ticked at this frame
        (bool)        : True if tangent split is ticked at this frame
    """
    for child in composite:
        if child.tag == "point_path":
            dictionary = ast.literal_eval(child.text)
            pos = get_vector_at_frame(dictionary, fr)
        elif child.tag == "width_path":
            dictionary = ast.literal_eval(child.text)
            width = to_Synfig_axis(get_vector_at_frame(dictionary, fr), "real")
        elif child.tag == "t1":
            t1 = child[0]
        elif child.tag == "t2":
            t2 = child[0]
        elif child.tag == "split_radius":
            split_r = child
        elif child.tag == "split_angle":
            split_a = child

    # Convert pos back to Synfig coordinates
    pos = to_Synfig_axis(pos, "vector")
    pos_ret = Vector(pos[0], pos[1])

    t1, t2 = get_tangent_at_frame(t1, t2, split_r, split_a, fr)
    # Convert to Synfig units
    t1 /= settings.PIX_PER_UNIT
    t2 /= settings.PIX_PER_UNIT

    split_r_val = get_bool_at_frame(split_r[0], fr)
    split_a_val = get_bool_at_frame(split_a[0], fr)

    return pos_ret, width, t1, t2, split_r_val, split_a_val
Example #17
0
def get_outline_param_at_frame(entry, fr):
    """
    Given a entry and frame, returns the parameters of the outline layer at
    that frame

    Args:
        entry (dict) : Vertex of outline layer in Synfig format
        fr        (int)                 : frame number

    Returns:
        (common.Vector.Vector) : position of the vertex
        (float)       : width of the vertex
        (common.Vector.Vector) : Tangent 1 of the vertex
        (common.Vector.Vector) : Tangent 2 of the vertex
        (bool)        : True if radius split is ticked at this frame
        (bool)        : True if tangent split is ticked at this frame
    """
    pos = entry["point"].get_value(fr)
    # Convert pos back to Synfig coordinates
    pos = to_Synfig_axis(pos, "vector")
    pos_ret = Vector(pos[0], pos[1])

    width = entry["width"].get_value(fr)
    width = to_Synfig_axis(width, "real")
    t1 = entry["t1"]
    t2 = entry["t2"]
    split_r = entry["split_radius"]
    split_a = entry["split_angle"]


    t1, t2 = get_tangent_at_frame(t1, t2, split_r, split_a, fr)
    # Convert to Synfig units
    t1 /= settings.PIX_PER_UNIT
    t2 /= settings.PIX_PER_UNIT

    split_r_val = split_r.get_value(fr)
    split_a_val = split_a.get_value(fr)

    return pos_ret, width, t1, t2, split_r_val, split_a_val
Example #18
0
def get_vector(waypoint):
    """
    Given a waypoint, it parses the string vector into Vector class defined in
    this converter

    Args:
        waypoint (lxml.etree._Element) : Synfig format waypoint

    Returns:
        (common.Vector.Vector) : x and y axis values stores in Vector format
    """
    # converting radius and angle to a vector
    if waypoint.tag == "radial_composite":
        for child in waypoint:
            if child.tag == "radius":
                radius = float(child[0].attrib["value"])
                radius *= settings.PIX_PER_UNIT
            elif child.tag == "theta":
                angle = float(child[0].attrib["value"])
        x, y = radial_to_tangent(radius, angle)
    else:
        x = float(waypoint[0][0].text)
        y = float(waypoint[0][1].text)
    return Vector(x, y)
Example #19
0
def synfig_circle(st_val, origin_param, radius_param, fr):
    """
    Calculates the points for the circle layer as in Synfig:
    https://github.com/synfig/synfig/blob/678cc3a7b1208fcca18c8b54a29a20576c499927/synfig-core/src/modules/mod_geometry/circle.cpp

    Args:
        st_val (dict) : Lottie format circle is stored in this
        origin (common.Param.Param) : Lottie format origin of circle
        radius (common.Param.Param) : Lottie format radius of circle
        fr (int) : Frame number

    Returns:
        (None)
    """

    num_splines = 8
    angle = 180.0 / num_splines
    angle *= ((math.pi * 2) / 360)
    k = 1.0 / math.cos(angle)

    radius = abs(to_Synfig_axis(radius_param.get_value(fr), "real"))
    origin = origin_param.get_value(fr)

    matrix = Matrix2()
    matrix.set_rotate(angle)

    p0, p1, p2 = Vector(), Vector(), Vector(radius, 0)

    # Setup chunk list
    chunk_list = []
    chunk_list.append([p2, Vector(), Vector()])
    i = 0
    while i < num_splines:
        p0 = p2
        p1 = matrix.get_transformed(p0)
        p2 = matrix.get_transformed(p1)
        cp1, cp2 = quadratic_to_cubic(p2, k * p1, p0)
        cur_tan = p2 - cp1
        chunk_list[-1][2] = cp2 - p0
        chunk_list.append([p2, cur_tan, Vector()])
        i += 1

    add(chunk_list, st_val, origin)
Example #20
0
def synfig_star(st_val, mx_points, origin_p, radius1_p, radius2_p, angle_p, points_p, regular_polygon_p, fr):
    """
    Calculates the points for the rectangle layer as in Synfig:
    https://github.com/synfig/synfig/blob/678cc3a7b1208fcca18c8b54a29a20576c499927/synfig-core/src/modules/mod_geometry/star.cpp

    Args:
        st_val (dict) : Lottie format star will be stored here
        mx_points (int) : Maximum points ever in star animation
        radius1_p (common.Param.Param) : Lottie format radius1 animation
        radius2_p (common.Param.Param) : Lottie format radius2 animation
        angle_p   (common.Param.Param) : Lottie format angle animation
        points_p  (common.Param.Param) : Lottie format points animation
        regular_polygon_p (common.Param.Param) : Synfig format regularPolygon animation
        fr (int) : Frame number

    Returns:
        (None)
    """

    angle = angle_p.get_value(fr)
    points = int(to_Synfig_axis(points_p.get_value(fr), "real"))
    radius1 = to_Synfig_axis(radius1_p.get_value(fr), "real")
    radius2 = to_Synfig_axis(radius2_p.get_value(fr), "real")
    regular_polygon = regular_polygon_p.get_value(fr)
    origin_cur = origin_p.get_value(fr)

    angle = math.radians(angle)
    dist_between_points = (math.pi * 2) / float(points)
    vector_list = []

    ####
    tot_points = 2*mx_points

    i = 0
    while i < points:
        dist1 = dist_between_points*i + angle
        dist2 = dist_between_points*i + dist_between_points/2 + angle
        vector_list.append(Vector(math.cos(dist1)*radius1, math.sin(dist1)*radius1))
        if not regular_polygon:
            vector_list.append(Vector(math.cos(dist2)*radius2, math.sin(dist2)*radius2))
        else:
            # This condition is needed because in lottie a shape must have equal
            # number of vertices at each frame
            vector_list.append(Vector(math.cos(dist1)*radius1, math.sin(dist1)*radius1))

        tot_points -= 2
        i += 1

    if len(vector_list) < 3:
        # Should throw error
        return

    while tot_points > 0:
        vector_list.append(vector_list[-1])
        tot_points -= 1

    # Setup chunk list
    chunk_list = []
    chunk_list.append([vector_list[0], Vector(), Vector()])
    i = 1
    while i < len(vector_list):
        if math.isnan(vector_list[i][0]) or math.isnan(vector_list[i][1]):
            break
        chunk_list.append([vector_list[i], Vector(), Vector()])
        i += 1

    add(chunk_list, st_val, origin_cur)
Example #21
0
def synfig_outline(bline, st_val, origin_p, outer_width_p, sharp_cusps_p, expand_p, r_tip0_p, r_tip1_p, homo_width_p, fr):
    """
    Calculates the points for the outline layer as in Synfig:
    https://github.com/synfig/synfig/blob/678cc3a7b1208fcca18c8b54a29a20576c499927/synfig-core/src/modules/mod_geometry/outline.cpp

    Args:
        bline_point (common.Bline.Bline) : Synfig format bline points of outline layer
        st_val (dict) : Lottie format outline stored in this
        origin_p (common.Param.Param) : Lottie format origin of outline layer
        outer_width_p (common.Param.Param) : Lottie format outer width
        sharp_cusps_p (common.Param.Param) : sharp cusps in Synfig format
        expand_p (common.Param.Param) : Lottie format expand parameter
        r_tip0_p (common.Param.Param) : Round tip[0] in Synfig format
        r_tip1_p (common.Param.Param) : Round tip[1] in Synfig format
        homo_width_p (common.Param.Param) : Homogeneous width in Synfig format
        fr (int) : Frame number

    Returns:
        (None)
    """

    EPSILON = 0.000000001
    SAMPLES = 50
    CUSP_TANGENT_ADJUST = 0.025
    CUSP_THRESHOLD = 0.40
    SPIKE_AMOUNT = 4
    ROUND_END_FACTOR = 4

    bline_list = bline.get_list_at_frame(fr)
    outer_width = to_Synfig_axis(outer_width_p.get_value(fr), "real")
    expand = to_Synfig_axis(expand_p.get_value(fr), "real")
    sharp_cusps = sharp_cusps_p.get_value(fr)
    r_tip0 = r_tip0_p.get_value(fr)
    r_tip1 = r_tip1_p.get_value(fr)
    homo_width = homo_width_p.get_value(fr)

    gv = get_outline_grow(fr)

    # Setup chunk list
    side_a, side_b = [], []

    # Check if looped
    loop = bline.get_loop()

    # Iterators
    end_it = len(bline_list)
    next_it = 0
    if loop:
        iter_it = end_it - 1
    else:
        iter_it = next_it
        next_it += 1

    first_point = bline_list[iter_it]
    first_tangent = bline_list[0].get_tangent2()
    last_tangent = first_point.get_tangent1()

    # If we are looped and drawing sharp cusps, we 'll need a value
    # for the incoming tangent. This code fails if we have a "degraded" spline
    # with just one vertex, so we avoid such case.
    if loop and sharp_cusps and last_tangent.is_equal_to(Vector(0, 0)) and len(bline_list) > 1:
        prev_it = iter_it
        prev_it -= 1
        prev_it %= len(bline_list)
        prev_point = bline_list[prev_it]
        curve = Hermite(prev_point.get_vertex(),
                        first_point.get_vertex(),
                        prev_point.get_tangent2(),
                        first_point.get_tangent1())
        last_tangent = curve.derivative(1.0 - CUSP_TANGENT_ADJUST)

    first = not loop
    while next_it != end_it:
        bp1 = bline_list[iter_it]
        bp2 = bline_list[next_it]

        # Setup tangents
        prev_t = bp1.get_tangent1()
        iter_t = bp1.get_tangent2()
        next_t = bp2.get_tangent1()

        split_flag = bp1.get_split_tangent_angle() or bp1.get_split_tangent_radius()

        # If iter_it.t2 == 0 and next.t1 == 0, this is a straight line
        if iter_t.is_equal_to(Vector(0, 0)) and next_t.is_equal_to(Vector(0, 0)):
            iter_t = next_t = bp2.get_vertex() - bp1.get_vertex()

            # If the 2 points are on top of each other, ignore this segment
            # leave 'first' true if was before
            if iter_t.is_equal_to(Vector(0, 0)):
                iter_it = next_it
                iter_it %= len(bline_list)
                next_it += 1
                continue

        # Setup the curve
        curve = Hermite(bp1.get_vertex(),
                        bp2.get_vertex(),
                        iter_t,
                        next_t)

        # Setup width's
        iter_w = gv*(bp1.get_width() * outer_width * 0.5 + expand)
        next_w = gv*(bp2.get_width() * outer_width * 0.5 + expand)

        if first:
            first_tangent = curve.derivative(CUSP_TANGENT_ADJUST)

        # Make cusps as necassary
        if not first and \
           sharp_cusps and \
           split_flag and \
           ((not prev_t.is_equal_to(iter_t)) or (iter_t.is_equal_to(Vector(0, 0)))) and \
           (not last_tangent.is_equal_to(Vector(0, 0))):

            curr_tangent = curve.derivative(CUSP_TANGENT_ADJUST)
            t1 = last_tangent.perp().norm()
            t2 = curr_tangent.perp().norm()

            cross = t1*t2.perp()
            perp = (t1 - t2).mag()
            if cross > CUSP_THRESHOLD:
                p1 = bp1.get_vertex() + t1*iter_w
                p2 = bp1.get_vertex() + t2*iter_w
                side_a.append([line_intersection(p1, last_tangent, p2, curr_tangent), Vector(0, 0), Vector(0, 0)])
            elif cross < -CUSP_THRESHOLD:
                p1 = bp1.get_vertex() - t1*iter_w
                p2 = bp1.get_vertex() - t2*iter_w
                side_b.append([line_intersection(p1, last_tangent, p2, curr_tangent), Vector(0, 0), Vector(0, 0)])
            elif cross > 0.0 and perp > 1.0:
                amount = max(0.0, cross/CUSP_THRESHOLD) * (SPIKE_AMOUNT - 1.0) + 1.0
                side_a.append([bp1.get_vertex() + (t1 + t2).norm()*iter_w*amount, Vector(0, 0), Vector(0, 0)])
            elif cross < 0 and perp > 1:
                amount = max(0.0, -cross/CUSP_THRESHOLD) * (SPIKE_AMOUNT - 1.0) + 1.0
                side_b.append([bp1.get_vertex() - (t1 + t2).norm()*iter_w*amount, Vector(0, 0), Vector(0, 0)])

        # Precalculate positions and coefficients
        length = 0.0
        points = []
        dists = []
        n = 0.0
        itr = 0
        while n < 1.000001:
            points.append(curve.value(n))
            if n:
                length += (points[itr] - points[itr-1]).mag()
            dists.append(length)

            n += 1.0/SAMPLES
            itr += 1
        length += (curve.value(1) - points[itr-1]).mag()

        div_length = 1
        if length > EPSILON:
            div_length = 1.0 / length

        # Might not need /3 for the tangents generated finally - VERY IMPORTANT
        # Make the outline
        pt = curve.derivative(CUSP_TANGENT_ADJUST) / 3
        n = 0.0
        itr = 0
        while n < 1.000001:
            t = curve.derivative(min(max(n, CUSP_TANGENT_ADJUST), 1.0 - CUSP_TANGENT_ADJUST)) / 3
            d = t.perp().norm()
            k = dists[itr] * div_length
            if not homo_width:
                k = n
            w = (next_w - iter_w)*k + iter_w
            if False and n:
                # create curve
                a = points[itr-1] + d*w
                b = points[itr] + d*w
                tk = (b - a).mag() * div_length
                side_a.append([b, pt*tk, -t*tk])

                a = points[itr-1] - d*w
                b = points[itr] - d*w
                tk = (b - a).mag() * div_length
                side_b.append([b, pt*tk, -t*tk])
            else:
                side_a.append([points[itr] + d*w, Vector(0, 0), Vector(0, 0)])
                side_b.append([points[itr] - d*w, Vector(0, 0), Vector(0, 0)])
            pt = t
            itr += 1
            n += 1.0/SAMPLES

        last_tangent = curve.derivative(1.0 - CUSP_TANGENT_ADJUST)
        side_a.append([curve.value(1.0) + last_tangent.perp().norm()*next_w, Vector(0, 0), Vector(0, 0)])
        side_b.append([curve.value(1.0) - last_tangent.perp().norm()*next_w, Vector(0, 0), Vector(0, 0)])
        first = False

        iter_it = next_it
        iter_it %= len(bline_list)
        next_it += 1

    if len(side_a) < 2 or len(side_b) < 2:
        return

    origin_cur = origin_p.get_value(fr)
    move_to(side_a[0][0], st_val, origin_cur)

    if loop:
        add(side_a, st_val, origin_cur)
        add_reverse(side_b, st_val, origin_cur)
    else:
        # Insert code for adding end tip
        if r_tip1:
            bp = bline_list[-1]
            vertex = bp.get_vertex()
            tangent = last_tangent.norm()
            w = gv*(bp.get_width() * outer_width * 0.5 + expand)

            a = vertex + tangent.perp()*w
            b = vertex - tangent.perp()*w
            p1 = a + tangent*w*(ROUND_END_FACTOR/3.0)
            p2 = b + tangent*w*(ROUND_END_FACTOR/3.0)
            tan = tangent*w*(ROUND_END_FACTOR/3.0)

            # replace the last point
            side_a[-1] = [a, Vector(0, 0), tan]
            add(side_a, st_val, origin_cur)
            add([[b, -tan, Vector(0, 0)]], st_val, origin_cur)
        else:
            add(side_a, st_val, origin_cur)

        # Insert code for adding beginning tip
        if r_tip0:
            bp = bline_list[0]
            vertex = bp.get_vertex()
            tangent = first_tangent.norm()
            w = gv*(bp.get_width() * outer_width * 0.5 + expand)

            a = vertex - tangent.perp()*w
            b = vertex + tangent.perp()*w
            p1 = a - tangent*w*(ROUND_END_FACTOR/3.0)
            p2 = b - tangent*w*(ROUND_END_FACTOR/3.0)
            tan = -tangent*w*(ROUND_END_FACTOR/3.0)

            # replace the first point
            side_b[0] = [a, Vector(0, 0), tan]
            add_reverse(side_b, st_val, origin_cur)
            add([[b, -tan, Vector(0, 0)]], st_val, origin_cur)
        else:
            add_reverse(side_b, st_val, origin_cur)
Example #22
0
def parse_position(animated, i):
    """
    To convert the synfig coordinates from units(initially a string) to pixels
    Depends on whether a vector is provided to it or a real value
    If real value is provided, then time is also taken into consideration

    Args:
        animated (lxml.etree._Element) : Stores animation which contains waypoints
        i        (int)                 : Iterator over animation

    Returns:
        (common.Vector.Vector) If the animated type is not color
        (common.Color.Color)  Else if the animated type is color
    """
    if animated.attrib["type"] == "vector":
        pos = [float(animated[i][0][0].text), float(animated[i][0][1].text)]
        pos = [settings.PIX_PER_UNIT * x for x in pos]

    elif animated.attrib["type"] in {"real", "circle_radius"}:
        pos = parse_value(animated, i)

    elif animated.attrib["type"] == "angle":
        pos = [
            get_angle(float(animated[i][0].attrib["value"])),
            get_frame(animated[i])
        ]

    elif animated.attrib["type"] == "base":
        pos = [
            float(animated[i][0].attrib["value"]) * settings.PIX_PER_UNIT,
            get_frame(animated[i])
        ]

    elif animated.attrib["type"] in {
            "composite_convert", "region_angle", "star_angle_new",
            "scalar_multiply"
    }:
        pos = [float(animated[i][0].attrib["value"]), get_frame(animated[i])]

    elif animated.attrib["type"] == "rotate_layer_angle":
        # Angle needs to made neg of what they are
        pos = [-float(animated[i][0].attrib["value"]), get_frame(animated[i])]

    elif animated.attrib["type"] == "opacity":
        pos = [
            float(animated[i][0].attrib["value"]) * settings.OPACITY_CONSTANT,
            get_frame(animated[i])
        ]

    elif animated.attrib["type"] == "effects_opacity":
        pos = [float(animated[i][0].attrib["value"]), get_frame(animated[i])]

    elif animated.attrib["type"] == "points":
        pos = [
            int(animated[i][0].attrib["value"]) * settings.PIX_PER_UNIT,
            get_frame(animated[i])
        ]

    elif animated.attrib["type"] == "bool":
        val = animated[i][0].attrib["value"]
        if val == "false":
            val = 0
        else:
            val = 1
        pos = [val, get_frame(animated[i])]

    elif animated.attrib["type"] == "rectangle_size":
        pos = parse_value(animated, i)
        vec = Vector(pos[0], pos[1], animated.attrib["type"])
        vec.add_new_val(
            float(animated[i][0].attrib["value2"]) * settings.PIX_PER_UNIT)
        return vec

    elif animated.attrib["type"] == "image_scale":
        val = float(animated[i][0].attrib["value"])
        val2 = get_frame(animated[i])
        vec = Vector(val, val2, animated.attrib["type"])
        vec.add_new_val(float(animated[i][0].attrib["value2"]))
        return vec

    elif animated.attrib["type"] == "scale_layer_zoom":
        val = (math.e**float(animated[i][0].attrib["value"])) * 100
        val2 = get_frame(animated[i])
        vec = Vector(val, val2, animated.attrib["type"])
        vec.add_new_val(val)
        return vec

    elif animated.attrib["type"] == "stretch_layer_scale":
        val1 = float(animated[i][0][0].text) * 100
        val3 = float(animated[i][0][1].text) * 100
        vec = Vector(val1, get_frame(animated[i]), animated.attrib["type"])
        vec.add_new_val(val3)
        return vec

    elif animated.attrib["type"] in {
            "group_layer_scale", "blur_anim_x", "blur_anim_y"
    }:
        if animated.attrib["type"] == "group_layer_scale":
            val1 = float(animated[i][0][0].text) * 100
            val3 = float(animated[i][0][1].text) * 100
            vec = Vector(val1, get_frame(animated[i]), animated.attrib["type"])
            vec.add_new_val(val3)
        elif animated.attrib["type"] == "blur_anim_x":
            val1 = float(animated[i][0][0].text) * 100
            vec = Vector(val1, get_frame(animated[i]), animated.attrib["type"])
        else:
            val1 = float(animated[i][0][1].text) * 100
            vec = Vector(val1, get_frame(animated[i]), animated.attrib["type"])
        return vec

    elif animated.attrib["type"] == "time":
        val = parse_time(animated[i][0].attrib["value"])  # Needed in seconds
        val2 = get_frame(animated[i])  # Needed in frames
        return Vector(val, val2, animated.attrib["type"])

    elif animated.attrib["type"] == "color":
        red = float(animated[i][0][0].text)
        green = float(animated[i][0][1].text)
        blue = float(animated[i][0][2].text)
        alpha = float(animated[i][0][3].text)
        red = red**(1 / settings.GAMMA[0])
        green = green**(1 / settings.GAMMA[1])
        blue = blue**(1 / settings.GAMMA[2])
        return Color(red, green, blue, alpha)

    elif animated.attrib["type"] == "gradient":
        return Gradient(animated[i][0])

    return Vector(pos[0], pos[1], animated.attrib["type"])
Example #23
0
def synfig_rectangle(st_val, point1_p, point2_p, expand_p, bevel_p, bevCircle, fr):
    """
    Calculates the points for the rectangle layer as in Synfig:
    https://github.com/synfig/synfig/blob/678cc3a7b1208fcca18c8b54a29a20576c499927/synfig-core/src/modules/mod_geometry/rectangle.cpp

    Args:
        st_val (dict) : Lottie format rectangle will be stored in this
        point1_p (self.Param.Param) : Lottie format point1 animation
        point2_p (self.Param.Param) : Lottie format point2 animation
        expand_p (self.Param.Param) : Lottie format expand parameter animation
        bevel_p (self.Param.Param) : Lottie format bevel parameter animation
        bevCircle (lxml.etree._Element) : Animation of bevCircle in Synfig format
        fr (int) : Frame Number

    Returns:
        (None)
    """

    expand = abs(to_Synfig_axis(expand_p.get_value(fr), "real"))
    bevel = abs(to_Synfig_axis(bevel_p.get_value(fr), "real"))
    p0 = to_Synfig_axis(point1_p.get_value(fr), "vector")
    p0 = Vector(p0[0], p0[1])
    p1 = to_Synfig_axis(point2_p.get_value(fr), "vector")
    p1 = Vector(p1[0], p1[1])
    if p1[0] < p0[0]:
        p0[0], p1[0] = p1[0], p0[0]
    if p1[1] < p0[1]:
        p0[1], p1[1] = p1[1], p0[1]

    bev_circle = bevCircle.get_value(fr)

    w = p1[0] - p0[0] + 2*expand
    h = p1[1] - p0[1] + 2*expand
    bev = bevel
    if bevel > 1:
        bev = 1
    if bev_circle:
        bevx = min(w*bev/2.0, h*bev/2.0)
        bevy = min(w*bev/2.0, h*bev/2.0)
    else:
        bevx = w*bev/2.0
        bevy = h*bev/2.0

    # Setup chunk list
    chunk_list = []

    if approximate_equal(bevel, 0.0):
        chunk_list.append([Vector(p0[0] - expand, p0[1] - expand), Vector(), Vector()])
        chunk_list.append([Vector(p1[0] + expand, p0[1] - expand), Vector(), Vector()])
        chunk_list.append([Vector(p1[0] + expand, p1[1] + expand), Vector(), Vector()])
        chunk_list.append([Vector(p0[0] - expand, p1[1] + expand), Vector(), Vector()])
    else:
        cur = Vector(p1[0] + expand - bevx, p0[1] - expand)
        chunk_list.append([cur, Vector(), Vector()])
        prev = cur

        cur = Vector(p1[0] + expand, p0[1] - expand + bevy)
        cp1, cp2 = quadratic_to_cubic(cur, Vector(p1[0] + expand, p0[1] - expand), prev)
        chunk_list[-1][2] = cp2 - prev
        chunk_list.append([cur, cur - cp1, Vector()])
        prev = cur

        cur = Vector(p1[0] + expand, p1[1] + expand - bevy)
        chunk_list.append([cur, Vector(), Vector()])
        prev = cur

        cur = Vector(p1[0] + expand - bevx, p1[1] + expand)
        cp1, cp2 = quadratic_to_cubic(cur, Vector(p1[0] + expand, p1[1] + expand), prev)
        chunk_list[-1][2] = cp2 - prev
        chunk_list.append([cur, cur - cp1, Vector()])
        prev = cur

        cur = Vector(p0[0] - expand + bevx, p1[1] + expand)
        chunk_list.append([cur, Vector(), Vector()])
        prev = cur

        cur = Vector(p0[0] - expand, p1[1] + expand - bevy)
        cp1, cp2 = quadratic_to_cubic(cur, Vector(p0[0] - expand, p1[1] + expand), prev)
        chunk_list[-1][2] = cp2 - prev
        chunk_list.append([cur, cur - cp1, Vector()])
        prev = cur

        cur = Vector(p0[0] - expand, p0[1] - expand + bevy)
        chunk_list.append([cur, Vector(), Vector()])
        prev = cur

        cur = Vector(p0[0] - expand + bevx, p0[1] - expand)
        cp1, cp2 = quadratic_to_cubic(cur, Vector(p0[0] - expand, p0[1] - expand), prev)
        chunk_list[-1][2] = cp2 - prev
        chunk_list.append([cur, cur - cp1, Vector()])
        prev = cur

    add(chunk_list, st_val, [0, 0], True)
Example #24
0
def gen_dynamic_list_polygon(lottie, dynamic_list):
    """
    Generates the bline corresponding to polygon layer

    Args:
        lottie (dict) : Lottie format polygon layer will be stored here
        dynamic_list (common.Param.Param) : Synfig format points of polygon

    Returns:
        (None)
    """
    ################## SECTION 1 ################
    # Inserting the waypoints if not animated, finding the first and last frame
    # Calculating the path after this
    window = {}
    window["first"] = sys.maxsize
    window["last"] = -1
    dynamic_list = Bline(dynamic_list[0], dynamic_list)

    for entry in dynamic_list.get_entry_list():
        pos = entry["vector"]
        pos.update_frame_window(window)

        z = Param(pos.getparent(), pos.getparent().getparent())
        z.animate("vector", True)
        entry["vector"] = z

    layer = dynamic_list.get_layer().get_layer()
    origin = layer.get_param("origin")

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

    if window["first"] == sys.maxsize and window["last"] == -1:
        window["first"] = window["last"] = 0
    ################ END OF SECTION 1 ##############

    ################ SECTION 2 #####################
    # Generating values for all the frames in the window
    fr = window["first"]
    while fr <= window["last"]:
        st_val, en_val = insert_dict_at(lottie, -1, fr, False)

        for entry in dynamic_list.get_entry_list():
            pos_cur = entry["vector"].get_value(fr)
            pos_next = entry["vector"].get_value(fr + 1)

            tangent1_cur, tangent2_cur = Vector(0, 0), Vector(0, 0)
            tangent1_next, tangent2_next = Vector(0, 0), Vector(0, 0)

            # Adding origin to each vertex
            origin_cur = origin.get_value(fr)
            origin_next = origin.get_value(fr + 1)
            for i in range(len(pos_cur)):
                pos_cur[i] += origin_cur[i]
            for i in range(len(pos_next)):
                pos_next[i] += origin_next[i]

            # Store values in dictionary
            st_val["i"].append(tangent1_cur.get_list())
            st_val["o"].append(tangent2_cur.get_list())
            st_val["v"].append(pos_cur)
            en_val["i"].append(tangent1_next.get_list())
            en_val["o"].append(tangent2_next.get_list())
            en_val["v"].append(pos_next)
        fr += 1
    # Setting the final time
    lottie.append({})
    lottie[-1]["t"] = fr
Example #25
0
    def get_list_at_frame(self, fr):
        """
        Returns the Bline list at a particular frame
        Refer: https://github.com/synfig/synfig/blob/15607089680af560ad031465d31878425af927eb/synfig-core/src/synfig/valuenodes/valuenode_bline.cpp
        """
        EPSILON = 0.0000001
        ret_list = []
        first_flag = True
        rising = [False]
        next_scale = 1.0

        first = BlinePoint(Vector(0, 0), 1, True, False, Vector(0, 0),
                           Vector(0, 0))
        first.set_origin(100)

        iterr = 0
        while iterr != self.get_len():
            entry = self.get_entry_list()[iterr]
            amount = entry["ActivepointList"].amount_at_time(fr, rising)
            assert (amount >= 0.0)
            assert (amount <= 1.0)

            # It's fully on
            if amount > 1.0 - EPSILON:
                if first_flag:
                    first_iter = iterr
                    first = prev = self.get_blinepoint(iterr, fr)
                    first_flag = False
                    ret_list.append(copy.deepcopy(first))
                    iterr += 1
                    continue
                curr = self.get_blinepoint(iterr, fr)

                if next_scale != 1.0:
                    ret_list[-1].set_split_tangent_both(True)
                    ret_list[-1].set_tangent2(prev.get_tangent2() * next_scale)
                    ret_list.append(copy.deepcopy(curr))
                    ret_list[-1].set_split_tangent_both(True)
                    ret_list[-1].set_tangent2(curr.get_tangent2())
                    ret_list[-1].set_tangent1(curr.get_tangent1() * next_scale)
                    next_scale = 1.0
                else:
                    ret_list.append(copy.deepcopy(curr))
                prev = curr

            # It's partly on
            elif amount > 0.0:
                blp_here_off = BlinePoint(Vector(0, 0), 1, True, False,
                                          Vector(0, 0), Vector(0, 0))
                blp_here_now = BlinePoint(Vector(0, 0), 1, True, False,
                                          Vector(0, 0), Vector(0, 0))
                blp_prev_off = BlinePoint(Vector(0, 0), 1, True, False,
                                          Vector(0, 0), Vector(0, 0))
                dist_from_begin = 0
                dist_from_end = 0

                if not rising[0]:
                    try:
                        on_time = self.get_entry_list(
                        )[iterr]["ActivepointList"].find_prev(fr).get_time()
                    except Exception as e:
                        on_time = settings.SOT
                    try:
                        off_time = self.get_entry_list(
                        )[iterr]["ActivepointList"].find_next(fr).get_time()
                    except Exception as e:
                        off_time = settings.EOT
                else:
                    try:
                        off_time = self.get_entry_list(
                        )[iterr]["ActivepointList"].find_prev(fr).get_time()
                    except Exception as e:
                        off_time = settings.SOT
                    try:
                        on_time = self.get_entry_list(
                        )[iterr]["ActivepointList"].find_next(fr).get_time()
                    except Exception as e:
                        on_time = settings.EOT

                blp_here_on = self.get_blinepoint(iterr, on_time)
                end_iter = iterr

                end_iter += 1
                while end_iter != self.get_len():
                    if self.get_entry_list(
                    )[end_iter]["ActivepointList"].amount_at_time(fr) > amount:
                        break
                    end_iter += 1

                if end_iter == self.get_len():
                    if self.get_loop() and (not first_flag):
                        end_iter = first_iter
                    else:
                        end_iter = self.get_len() - 1

                blp_next_off = self.get_blinepoint(end_iter, off_time)

                begin_iter = iterr
                blp_prev_off.set_origin(100)

                while True:
                    if begin_iter == 0:
                        if self.get_loop():
                            begin_iter = self.get_len()
                        else:
                            break
                    begin_iter -= 1
                    dist_from_begin += 1

                    if begin_iter == iterr:
                        break

                    if self.get_entry_list()[begin_iter][
                            "ActivepointList"].amount_at_time(fr) > amount:
                        blp_prev_off = self.get_blinepoint(
                            begin_iter, off_time)
                        break

                if blp_prev_off.get_origin() == 100:
                    if first_flag:
                        begin_iter = 0
                    else:
                        begin_iter = first_iter
                    blp_prev_off = self.get_blinepoint(begin_iter, off_time)

                curve = Hermite(blp_prev_off.get_vertex(),
                                blp_next_off.get_vertex(),
                                blp_prev_off.get_tangent2(),
                                blp_next_off.get_tangent1())

                blp_here_off.set_vertex(curve.value(blp_here_on.get_origin()))
                blp_here_off.set_width(
                    (blp_next_off.get_width() - blp_prev_off.get_width()) *
                    blp_here_on.get_origin() + blp_prev_off.get_width())
                blp_here_off.set_tangent1(
                    curve.derivative(blp_here_on.get_origin()))
                blp_here_off.set_tangent2(
                    curve.derivative(blp_here_on.get_origin()))

                if begin_iter == (iterr - 1) or dist_from_begin == 1:
                    prev_tangent_scalar = self.linear_interpolation(
                        blp_here_on.get_origin(), 1.0, amount)
                else:
                    prev_tangent_scalar = self.linear_interpolation(
                        blp_here_on.get_origin() - prev.get_origin(), 1.0,
                        amount)

                if end_iter == (iterr + 1) or dist_from_end == 1:
                    next_tangent_scalar = self.linear_interpolation(
                        1.0 - blp_here_on.get_origin(), 1.0, amount)
                elif self.get_len() != (iterr + 1):
                    nextt = self.get_blinepoint(iterr + 1, fr)
                    next_tangent_scalar = self.linear_interpolation(
                        nextt.get_origin() - blp_here_on.get_origin(), 1.0,
                        amount)
                else:
                    next_tangent_scalar = self.linear_interpolation(
                        blp_next_off.get_origin() - blp_here_on.get_origin(),
                        1.0, amount)
                next_scale = next_tangent_scalar

                # My second try
                off_coord_sys = []
                on_coord_sys = []
                curr_coord_sys = []
                end_pos_at_off_time = self.get_blinepoint(
                    end_iter, off_time).get_vertex()
                begin_pos_at_off_time = self.get_blinepoint(
                    begin_iter, off_time).get_vertex()
                off_coord_origin = (begin_pos_at_off_time +
                                    end_pos_at_off_time) / 2
                off_coord_sys.append(
                    (begin_pos_at_off_time - end_pos_at_off_time).norm())
                off_coord_sys.append(off_coord_sys[0].perp())

                end_pos_at_on_time = self.get_blinepoint(end_iter,
                                                         on_time).get_vertex()
                begin_pos_at_on_time = self.get_blinepoint(
                    begin_iter, on_time).get_vertex()
                on_coord_origin = (begin_pos_at_on_time +
                                   end_pos_at_on_time) / 2
                on_coord_sys.append(
                    (begin_pos_at_on_time - end_pos_at_on_time).norm())
                on_coord_sys.append(on_coord_sys[0].perp())

                end_pos_at_current_time = self.get_blinepoint(end_iter,
                                                              fr).get_vertex()
                begin_pos_at_current_time = self.get_blinepoint(
                    begin_iter, fr).get_vertex()
                curr_coord_origin = (begin_pos_at_current_time +
                                     end_pos_at_current_time) / 2
                curr_coord_sys.append((begin_pos_at_current_time -
                                       end_pos_at_current_time).norm())
                curr_coord_sys.append(curr_coord_sys[0].perp())

                # swapping
                temp = curr_coord_sys[0][1]
                curr_coord_sys[0][1] = curr_coord_sys[1][0]
                curr_coord_sys[1][0] = temp

                trans_on_point = Vector(0, 0)
                trans_off_point = Vector(0, 0)
                trans_on_t1 = Vector(0, 0)
                trans_off_t1 = Vector(0, 0)
                trans_on_t2 = Vector(0, 0)
                trans_off_t2 = Vector(0, 0)

                trans_on_point = self.transform_coords(
                    blp_here_on.get_vertex(), trans_on_point, on_coord_origin,
                    on_coord_sys)
                trans_off_point = self.transform_coords(
                    blp_here_off.get_vertex(), trans_off_point,
                    off_coord_origin, off_coord_sys)

                trans_on_t1 = self.transform_coords(blp_here_on.get_tangent1(),
                                                    trans_on_t1, Vector(0, 0),
                                                    on_coord_sys)
                trans_off_t1 = self.transform_coords(
                    blp_here_off.get_tangent1(), trans_off_t1, Vector(0, 0),
                    off_coord_sys)

                if blp_here_on.get_split_tangent_both():
                    trans_on_t2 = self.transform_coords(
                        blp_here_on.get_tangent2(), trans_on_t2, Vector(0, 0),
                        on_coord_sys)
                    trans_off_t2 = self.transform_coords(
                        blp_here_off.get_tangent2(), trans_off_t2,
                        Vector(0, 0), off_coord_sys)

                tmp = Vector(0, 0)
                tmp = self.untransform_coords(
                    self.linear_interpolation(trans_off_point, trans_on_point,
                                              amount), tmp, curr_coord_origin,
                    curr_coord_sys)
                blp_here_now.set_vertex(tmp)

                tmp = Vector(0, 0)
                tmp = self.untransform_coords(
                    self.radial_interpolation(trans_off_t1,
                                              trans_on_t1, amount), tmp,
                    Vector(0, 0), curr_coord_sys)
                blp_here_now.set_tangent1(tmp)

                # blp_here_now.set_tangent1(self.radial_interpolation(blp_here_off.get_tangent1(), blp_here_on.get_tangent1(), amount))

                if blp_here_on.get_split_tangent_both():
                    blp_here_now.set_split_tangent_both(True)
                    tmp = Vector(0, 0)
                    tmp = self.untransform_coords(
                        self.radial_interpolation(trans_off_t2,
                                                  trans_on_t2, amount), tmp,
                        Vector(0, 0), curr_coord_sys)
                    blp_here_now.set_tangent2(tmp)
                else:
                    blp_here_now.set_split_tangent_both(False)

                blp_here_now.set_origin(blp_here_on.get_origin())
                blp_here_now.set_width(
                    self.linear_interpolation(blp_here_off.get_width(),
                                              blp_here_on.get_width(), amount))

                if first_flag:
                    blp_here_now.set_tangent1(blp_here_now.get_tangent1() *
                                              prev_tangent_scalar)
                    first_iter = iterr
                    first = prev = blp_here_now
                    first_flag = False
                    ret_list.append(copy.deepcopy(blp_here_now))
                    iterr += 1
                    continue

                ret_list[-1].set_split_tangent_both(True)
                ret_list[-1].set_tangent2(prev.get_tangent2() *
                                          prev_tangent_scalar)

                ret_list.append(copy.deepcopy(blp_here_now))
                ret_list[-1].set_split_tangent_both(True)
                ret_list[-1].set_tangent1(blp_here_now.get_tangent1() *
                                          prev_tangent_scalar)
                prev = blp_here_now

            iterr += 1

        if next_scale != 1:
            ret_list[-1].set_split_tangent_both(True)
            ret_list[-1].set_tangent2(prev.get_tangent2() * next_scale)

        return ret_list
Example #26
0
def gen_dynamic_list_polygon(lottie, dynamic_list):
    """
    Generates the bline corresponding to polygon layer

    Args:
        lottie (dict) : Lottie format polygon layer will be stored here
        dynamic_list (lxml.etree._Element) : Synfig format points of polygon

    Returns:
        (None)
    """
    ################## SECTION 1 ################
    # Inserting the waypoints if not animated, finding the first and last frame
    # Calculating the path after this
    window = {}
    window["first"] = sys.maxsize
    window["last"] = -1
    count = 0

    for entry in dynamic_list:
        pos = entry
        update_frame_window(pos[0], window)

        new_pos = gen_dummy_waypoint(pos, "entry", "vector")
        pos.getparent().remove(pos)
        dynamic_list.insert(count, new_pos)

        append_path(new_pos[0], dynamic_list[count], "pos_path", "vector")

        count += 1

    layer = dynamic_list.getparent().getparent()
    for chld in layer:
        if chld.tag == "param":
            if chld.attrib["name"] == "origin":
                origin = chld

    # Animating the origin
    update_frame_window(origin[0], window)
    origin_parent = origin.getparent()
    origin = gen_dummy_waypoint(origin, "param", "vector", "origin")
    update_child_at_parent(origin_parent, origin, "param", "origin")

    # Generate path for the origin component
    origin_dict = {}
    origin[0].attrib["transform_axis"] = "true"
    gen_properties_multi_dimensional_keyframed(origin_dict, origin[0], 0)

    if window["first"] == sys.maxsize and window["last"] == -1:
        window["first"] = window["last"] = 0
    ################ END OF SECTION 1 ##############

    ################ SECTION 2 #####################
    # Generating values for all the frames in the window
    fr = window["first"]
    while fr <= window["last"]:
        st_val, en_val = insert_dict_at(lottie, -1, fr, False)

        for entry in dynamic_list:
            # Only two childs, one should be animated, other one is path
            for child in entry:
                if child.tag == "pos_path":
                    dictionary = ast.literal_eval(child.text)
                    pos_cur = get_vector_at_frame(dictionary, fr)
                    pos_next = get_vector_at_frame(dictionary, fr + 1)

            tangent1_cur, tangent2_cur = Vector(0, 0), Vector(0, 0)
            tangent1_next, tangent2_next = Vector(0, 0), Vector(0, 0)

            # Adding origin to each vertex
            origin_cur = get_vector_at_frame(origin_dict, fr)
            origin_next = get_vector_at_frame(origin_dict, fr + 1)
            for i in range(len(pos_cur)):
                pos_cur[i] += origin_cur[i]
            for i in range(len(pos_next)):
                pos_next[i] += origin_next[i]

            # Store values in dictionary
            st_val["i"].append(tangent1_cur.get_list())
            st_val["o"].append(tangent2_cur.get_list())
            st_val["v"].append(pos_cur)
            en_val["i"].append(tangent1_next.get_list())
            en_val["o"].append(tangent2_next.get_list())
            en_val["v"].append(pos_next)
        fr += 1
    # Setting the final time
    lottie.append({})
    lottie[-1]["t"] = fr