def extract_bones(self, bones_dict): """ Will store all the bones in a dictionary """ for chld in self.canvas: if chld.tag == "bones": bones = chld for child in bones: key = child.attrib["guid"] bones_dict[key] = Param(child, Param(bones, self))
def gen_layer_translate(lottie, layer): """ Help generate transform properties of translate layer Args: lottie (dict) : Transform properties in lottie format layer (common.Layer.Layer) : Transform properties in Synfig format Returns: (None) """ origin = layer.get_param("origin") origin.animate("vector") pos = origin st = "<param name='anchor'><vector><x>0.00</x><y>0.00</y></vector></param>" anchor = etree.fromstring(st) anchor = Param(anchor, layer) anchor.animate("vector") anchor.add_offset() if settings.INSIDE_PRECOMP: pos.add_offset() anchor.animate("vector", True) pos.animate("vector", True) gen_helpers_transform(lottie, pos, anchor)
def gen_image_scale(animated_1, animated_2, width, height): """ In Synfig, no scale parameter is available for image layer, so it will be created here for Lottie conversion Args: animated_1 (common.Param.Param): point1 animation in Synfig format animated_2 (common.Param.Param): point2 animation in Synfig format width (int) : Width of the original image height (int) : Height of the original image Returns: (lxml.etree._Element) : Scale parameter in Synfig format """ st = '<param name="image_scale"><real value="0.0000000000"/></param>' root = etree.fromstring(st) image_scale = Param(root, None) #image_scale.animate("image_scale") image_scale.animate_without_path("image_scale") window = {} window["first"] = sys.maxsize window["last"] = -1 animated_1.update_frame_window(window) animated_2.update_frame_window(window) # Minimizing the window size if window["first"] == sys.maxsize and window["last"] == -1: window["first"] = window["last"] = 0 fr = window["first"] # Filling the first 2 frames with there original scale values fill_image_scale_at_frame(image_scale[0], animated_1, animated_2, width, height, fr) fill_image_scale_at_frame(image_scale[0], animated_1, animated_2, width, height, fr + 1) fr += 2 while fr <= window["last"]: new_waypoint = copy.deepcopy(root[0][0]) time = fr / settings.lottie_format["fr"] time = str(time) + "s" new_waypoint.attrib["time"] = time root[0].append(new_waypoint) fill_image_scale_at_frame(image_scale[0], animated_1, animated_2, width, height, fr) fr += 1 return image_scale
def add_param(self, key, param): """ param is of type __something__ Manually adding some parameter """ self.params[key] = Param(param, self) return self.params[key]
def extract_params(self, params): """ Will extract the parameters from the layer and store in params """ for child in self.layer: if child.tag == "param": key = child.attrib["name"] params[key] = Param(child, self) self.set_group_params()
def get_param(self, *keys): """ Given a key, this will return the address of the child corresponding to it If multiple keys are given, it will return the key found first """ for key in keys: if key in self.params.keys(): return self.params[key] return Param(None, None)
def animate_tangents(tangent, window): """ Animates the radial composite and updates the window of frame if radial composite's parameters are already animated Also generate the Lottie path and stores in radial_composite Args: tangent (common.Param.Param) : Synfig format radial composite's parent-> stores radius and angle window (dict) : max and min frame of overall animations stored in this Returns: (None) """ for child in tangent[0]: # Assuming tangent[0] is always radial_composite if child.tag == "radius": radius = Param(child, tangent[0]) elif child.tag == "theta": theta = Param(child, tangent[0]) radius.update_frame_window(window) theta.update_frame_window(window) radius.animate("real") theta.animate("region_angle") tangent.add_subparam("radius", radius) tangent.add_subparam("theta", theta)
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()
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