def gen_layer_shape(lottie, layer, idx): """ Generates the dictionary corresponding to layers/shape.json Args: lottie (dict) : Lottie generate shape stored here layer (common.Layer.Layer) : Synfig format shape layer idx (int) : Stores the index(number of) of shape layer Returns: (None) """ if layer.get_type() in {"linear_gradient", "radial_gradient"}: # Create dummy point1 and point2 for linear/radial gradient to generate rectangle for it in lottie format # Will have to use add_offset() function inside after this generation gen_dummy_rectangle(layer) layer.add_offset() index = Count() lottie["ddd"] = settings.DEFAULT_3D lottie["ind"] = idx lottie["ty"] = settings.LAYER_SHAPE_TYPE lottie["nm"] = layer.get_description() lottie["sr"] = settings.LAYER_DEFAULT_STRETCH lottie["ks"] = {} # Transform properties to be filled gen_helpers_transform(lottie["ks"]) lottie["ao"] = settings.LAYER_DEFAULT_AUTO_ORIENT lottie["shapes"] = [] # Shapes to be filled yet lottie["shapes"].append({}) if layer.get_type() == "star": gen_shapes_star(lottie["shapes"][0], layer, index.inc()) elif layer.get_type() in {"circle", "simple_circle"}: gen_shapes_circle(lottie["shapes"][0], layer, index.inc()) elif layer.get_type() in {"filled_rectangle", "rectangle"}: gen_shapes_rectangle(lottie["shapes"][0], layer.get_layer(), index.inc()) elif layer.get_type() in {"linear_gradient", "radial_gradient"}: gen_shapes_shape(lottie["shapes"][0], layer, index.inc()) elif layer.get_type() in {"outline"}: settings.OUTLINE_FLAG = True gen_bline_outline_constant(lottie["shapes"][0],layer.get_param("bline"),layer,lottie["ks"],index.inc()) lottie["shapes"].append({}) # For the fill or color if layer.get_type() in {"linear_gradient"}: gen_linear_gradient(lottie["shapes"][1], layer, index.inc()) elif layer.get_type() in {"radial_gradient"}: gen_radial_gradient(lottie["shapes"][1], layer, index.inc()) elif layer.get_type() in {"outline"}: pass else: gen_shapes_fill(lottie["shapes"][1], layer) lottie["ip"] = settings.lottie_format["ip"] lottie["op"] = settings.lottie_format["op"] lottie["st"] = 0 # Don't know yet get_blend(lottie, layer)
def gen_layer_image(lottie, layer, idx): """ Generates the dictionary corresponding to layers/image.json Args: lottie (dict) : Lottie generated image stored here layer (common.Layer.Layer) : Synfig format image layer idx (int) : Stores the index(number of) of image layer Returns: (None) """ layer.add_offset() lottie["ddd"] = settings.DEFAULT_3D lottie["ind"] = idx lottie["ty"] = settings.LAYER_IMAGE_TYPE lottie["nm"] = layer.get_description() 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"] st["tl"].animate("vector") st["br"].animate("vector") st["scale"] = gen_image_scale(st["tl"], st["br"], asset["w"], asset["h"]) # Animation of this scale is needed again, as helpers/transform does not do # path calculation again st["scale"].animate("image_scale") anchor = settings.DEFAULT_ANCHOR rotation = settings.DEFAULT_ROTATION opacity = layer.get_param("amount") opacity.animate("opacity") gen_helpers_transform(lottie["ks"], st["tl"], anchor, st["scale"], rotation, opacity) 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)
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) """ index = Count() lottie["ddd"] = settings.DEFAULT_3D lottie["ind"] = idx lottie["ty"] = settings.LAYER_IMAGE_TYPE lottie["nm"] = settings.LAYER_IMAGE_NAME + str(idx) 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"], pos1_animate, "vector") # If pos2 is not animated if pos2_animate in {0, 1}: st["br"] = gen_dummy_waypoint(st["br"], pos2_animate, "vector") st["scale"] = gen_image_scale(st["tl"][0], st["br"][0], asset["w"], asset["h"]) anchor = [0, 0, 0] gen_helpers_transform(lottie["ks"], layer, st["tl"][0], anchor, st["scale"][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) lottie["markers"] = [] # Markers to be filled yet
def gen_layer_solid(lottie, layer, idx): """ Generates the dictionary corresponding to layers/solid.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) """ 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 for chld in layer: if chld.tag == "param": if chld.attrib["name"] == "color": lottie["sc"] = get_color_hex(chld[0]) # Solid Color lottie["ip"] = settings.lottie_format["ip"] lottie["op"] = settings.lottie_format["op"] lottie["st"] = 0 # Don't know yet get_blend(lottie, layer)
def gen_layer_solid(lottie, layer, idx): """ Generates the dictionary corresponding to layers/solid.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) """ 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]) lottie["ip"] = settings.lottie_format["ip"] lottie["op"] = settings.lottie_format["op"] lottie["st"] = 0 # Don't know yet get_blend(lottie, layer)
def gen_layer_shape(lottie, layer, idx): """ Generates the dictionary corresponding to layers/shape.json Args: lottie (dict) : Lottie generate shape stored here layer (common.Layer.Layer) : Synfig format shape layer idx (int) : Stores the index(number of) of shape layer Returns: (None) """ layer.add_offset() index = Count() lottie["ddd"] = settings.DEFAULT_3D lottie["ind"] = idx lottie["ty"] = settings.LAYER_SHAPE_TYPE lottie["nm"] = layer.get_description() lottie["sr"] = settings.LAYER_DEFAULT_STRETCH lottie["ks"] = {} # Transform properties to be filled gen_helpers_transform(lottie["ks"]) lottie["ao"] = settings.LAYER_DEFAULT_AUTO_ORIENT lottie["shapes"] = [] # Shapes to be filled yet lottie["shapes"].append({}) if layer.get_type() == "star": gen_shapes_star(lottie["shapes"][0], layer, index.inc()) elif layer.get_type() in {"circle", "simple_circle"}: gen_shapes_circle(lottie["shapes"][0], layer, index.inc()) elif layer.get_type() in {"filled_rectangle", "rectangle"}: gen_shapes_rectangle(lottie["shapes"][0], layer.get_layer(), index.inc()) lottie["shapes"].append({}) # For the fill or color gen_shapes_fill(lottie["shapes"][1], layer) lottie["ip"] = settings.lottie_format["ip"] lottie["op"] = settings.lottie_format["op"] lottie["st"] = 0 # Don't know yet get_blend(lottie, layer)
def gen_layer_shape(lottie, layer, idx): """ Generates the dictionary corresponding to layers/shape.json Args: lottie (dict) : Lottie generate shape stored here layer (lxml.etree._Element): Synfig format shape layer idx (int) : Stores the index(number of) of shape layer Returns: (None) """ index = Count() lottie["ddd"] = settings.DEFAULT_3D lottie["ind"] = idx lottie["ty"] = settings.LAYER_SHAPE_TYPE lottie["nm"] = settings.LAYER_SHAPE_NAME + str(idx) lottie["sr"] = settings.LAYER_DEFAULT_STRETCH lottie["ks"] = {} # Transform properties to be filled pos = [0, 0] # default anchor = [0, 0, 0] # default scale = [100, 100, 100] # default gen_helpers_transform(lottie["ks"], layer, pos, anchor, scale) lottie["ao"] = settings.LAYER_DEFAULT_AUTO_ORIENT lottie["shapes"] = [] # Shapes to be filled yet lottie["shapes"].append({}) if layer.attrib["type"] == "star": gen_shapes_star(lottie["shapes"][0], layer, index.inc()) elif layer.attrib["type"] in {"circle", "simple_circle"}: gen_shapes_circle(lottie["shapes"][0], layer, index.inc()) elif layer.attrib["type"] == "rectangle": gen_shapes_rectangle(lottie["shapes"][0], layer, index.inc()) lottie["shapes"].append({}) # For the fill or color gen_shapes_fill(lottie["shapes"][1], layer) lottie["ip"] = settings.lottie_format["ip"] lottie["op"] = settings.lottie_format["op"] lottie["st"] = 0 # Don't know yet get_blend(lottie, layer) lottie["markers"] = [] # Markers to be filled yet
def gen_layer_group(lottie, layer, idx): """ Will generate a pre composition but has small differences than pre-comp layer used in layers/preComp.py This function will be used for group layer as well as switch group layer Args: lottie (dict) : Lottie format layer will be stored here layer (lxml.etree._Element) : Synfig format group/switch layer idx (int) : Index of the layer Returns: (None) """ lottie["ddd"] = settings.DEFAULT_3D lottie["ind"] = idx lottie["ty"] = settings.LAYER_PRECOMP_TYPE lottie["sr"] = settings.LAYER_DEFAULT_STRETCH lottie["ks"] = {} # Transform properties to be filled set_layer_desc(layer, settings.LAYER_PRECOMP_NAME + str(idx), lottie) index = Count() for chld in layer: if chld.tag == "param": if chld.attrib["name"] == "canvas": canvas = chld elif chld.attrib["name"] == "transformation": transform = chld[0] for child in transform: if child.tag == "scale": scale = child elif child.tag == "offset": pos = child elif child.tag == "angle": angle = child elif chld.attrib["name"] == "origin": origin = chld elif chld.attrib["name"] == "amount": opacity = chld elif chld.attrib["name"] == "outline_grow": outline_grow = chld elif chld.attrib["name"] == "time_offset": time_offset = chld elif chld.attrib["name"] == "time_dilation": time_dilation = chld outline_grow = gen_dummy_waypoint(outline_grow, "param", "real") append_path(outline_grow[0], outline_grow, "outline_grow_path") origin = gen_dummy_waypoint(origin, "param", "vector") anchor = origin group.update_pos(anchor) angle = gen_dummy_waypoint(angle, "angle", "rotate_layer_angle") pos = gen_dummy_waypoint(pos, "offset", "vector") if settings.INSIDE_PRECOMP: group.update_pos(pos) scale = gen_dummy_waypoint(scale, "scale", "group_layer_scale") # Generate the transform properties here gen_helpers_transform(lottie["ks"], layer, pos[0], anchor[0], scale[0], angle[0], opacity[0]) # Store previous states, to be recovered at the end of group layer prev_state = settings.INSIDE_PRECOMP settings.OUTLINE_GROW.append(outline_grow) settings.INSIDE_PRECOMP = True settings.lottie_format["assets"].append({}) asset = add_precomp_asset(settings.lottie_format["assets"][-1], canvas[0], len(canvas[0])) lottie["refId"] = asset lottie["w"] = settings.lottie_format[ "w"] + settings.ADDITIONAL_PRECOMP_WIDTH # Experimental increase in width and height of precomposition lottie[ "h"] = settings.lottie_format["h"] + settings.ADDITIONAL_PRECOMP_HEIGHT 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) # Time offset and speed lottie["tm"] = {} gen_time_remap(lottie["tm"], time_offset, time_dilation, index.inc()) # Change opacity of layers for switch-group layers if layer.attrib["type"] == "switch": change_opacity_switch(layer, lottie) # Change opacity of layers for group layers elif layer.attrib["type"] == "group": change_opacity_group(layer, lottie) # Return to previous state, when we go outside the group layer settings.INSIDE_PRECOMP = prev_state settings.OUTLINE_GROW.pop()
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())
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())
def gen_layer_group(lottie, layer, idx): """ Will generate a pre composition but has small differences than pre-comp layer used in layers/preComp.py This function will be used for group layer as well as switch group layer Args: lottie (dict) : Lottie format layer will be stored here layer (common.Layer.Layer) : Synfig format group/switch layer idx (int) : Index of the layer Returns: (None) """ lottie["ddd"] = settings.DEFAULT_3D lottie["ind"] = idx lottie["ty"] = settings.LAYER_PRECOMP_TYPE lottie["sr"] = settings.LAYER_DEFAULT_STRETCH lottie["ks"] = {} # Transform properties to be filled lottie["nm"] = layer.get_description() index = Count() # Extract parameters canvas = Canvas(layer.get_param("canvas")) origin = layer.get_param("origin") opacity = layer.get_param("amount") outline_grow = layer.get_param("outline_grow") time_offset = layer.get_param("time_offset") time_dilation = layer.get_param("time_dilation") transformation = layer.get_param("transformation") transform = transformation[0] try_par = Param(transform, Param(transformation.get(), layer)) for child in transform: if child.tag == "scale": scale = Param(child, try_par) elif child.tag == "offset": pos = Param(child, try_par) elif child.tag == "angle": angle = Param(child, try_par) elif child.tag == "skew_angle": skew = Param(child, try_par) outline_grow.animate("real") origin.animate("vector") anchor = origin anchor.add_offset() angle.animate("rotate_layer_angle") pos.animate("vector") if settings.INSIDE_PRECOMP: pos.add_offset() scale.animate("group_layer_scale") # Generating animation for skew skew.animate("rotate_layer_angle") # Animating opacity opacity.animate("opacity") # Reset the animations after adding offset anchor.animate("vector", True) pos.animate("vector", True) # Generate the transform properties here gen_helpers_transform(lottie["ks"], pos, anchor, scale, angle, opacity, skew) # Store previous states, to be recovered at the end of group layer prev_state = settings.INSIDE_PRECOMP settings.OUTLINE_GROW.append( outline_grow ) # Storing the outline grow in settings, will be used inside child outlines settings.INSIDE_PRECOMP = True settings.lottie_format["assets"].append({}) asset = add_precomp_asset(settings.lottie_format["assets"][-1], canvas, canvas.get_num_layers()) lottie["refId"] = asset lottie["w"] = settings.lottie_format[ "w"] + settings.ADDITIONAL_PRECOMP_WIDTH # Experimental increase in width and height of precomposition lottie[ "h"] = settings.lottie_format["h"] + settings.ADDITIONAL_PRECOMP_HEIGHT 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) # Time offset and speed lottie["tm"] = {} gen_time_remap(lottie["tm"], time_offset, time_dilation, index.inc()) # Change opacity of layers for switch-group layers if layer.get_type() == "switch": change_opacity_switch(layer, lottie) # Change opacity of layers for group layers elif layer.get_type() == "group": change_opacity_group(layer, lottie) # Return to previous state, when we go outside the group layer settings.INSIDE_PRECOMP = prev_state settings.OUTLINE_GROW.pop()