File indexing completed on 2025-01-19 03:59:52

0001 import warnings
0002 from .base import LottieObject, LottieProp, PseudoBool, LottieEnum
0003 from .effects import Effect
0004 from .helpers import Transform, Mask
0005 from .shapes import ShapeElement
0006 from .text import TextAnimatorData
0007 from .properties import Value
0008 
0009 
0010 ## @ingroup Lottie
0011 class BlendMode(LottieEnum):
0012     Normal = 0
0013     Multiply = 1
0014     Screen = 2
0015     Overlay = 3
0016     Darken = 4
0017     Lighten = 5
0018     ColorDodge = 6
0019     ColorBurn = 7
0020     HardLight = 8
0021     SoftLight = 9
0022     Difference = 10
0023     Exclusion = 11
0024     Hue = 12
0025     Saturation = 13
0026     Color = 14
0027     Luminosity = 15
0028 
0029 
0030 ## @ingroup Lottie
0031 ## @todo SVG masks
0032 class MatteMode(LottieEnum):
0033     Normal = 0
0034     Alpha = 1
0035     InvertedAlpha = 2
0036     Luma = 3
0037     InvertedLuma = 4
0038 
0039 
0040 ## @ingroup Lottie
0041 class Layer(LottieObject):
0042     _props = [
0043         LottieProp("threedimensional", "ddd", PseudoBool, False),
0044         LottieProp("hidden", "hd", bool, False),
0045         LottieProp("type", "ty", int, False),
0046         LottieProp("name", "nm", str, False),
0047         LottieProp("parent_index", "parent", int, False),
0048 
0049         LottieProp("stretch", "sr", float, False),
0050         LottieProp("transform", "ks", Transform, False),
0051         LottieProp("auto_orient", "ao", PseudoBool, False),
0052 
0053         LottieProp("in_point", "ip", float, False),
0054         LottieProp("out_point", "op", float, False),
0055         LottieProp("start_time", "st", float, False),
0056         LottieProp("blend_mode", "bm", BlendMode, False),
0057 
0058         LottieProp("matte_mode", "tt", MatteMode, False),
0059         LottieProp("index", "ind", int, False),
0060         #LottieProp("css_class", "cl", str, False),
0061         #LottieProp("layer_html_id", "ln", str, False),
0062         LottieProp("has_masks", "hasMask", bool, False),
0063         LottieProp("masks", "masksProperties", Mask, True),
0064         LottieProp("effects", "ef", Effect, True),
0065     ]
0066     ## %Layer type.
0067     ## @see https://github.com/bodymovin/bodymovin-extension/blob/master/bundle/jsx/enums/layerTypes.jsx
0068     type = None
0069     _classses = {}
0070 
0071     @property
0072     def has_masks(self):
0073         """!
0074         Whether the layer has some masks applied
0075         """
0076         return bool(self.masks) if getattr(self, "masks") is not None else None
0077 
0078     def __init__(self):
0079         ## Transform properties
0080         self.transform = Transform()
0081         ## Auto-Orient along path AE property.
0082         self.auto_orient = False
0083         ## 3d layer flag
0084         self.threedimensional = False
0085         ## Hidden layer
0086         self.hidden = None
0087         ## Layer index in AE. Used for parenting and expressions.
0088         self.index = None
0089 
0090         """
0091         # Parsed layer name used as html class on SVG/HTML renderer
0092         #self.css_class = ""
0093         # Parsed layer name used as html id on SVG/HTML renderer
0094         #self.layer_html_id = ""
0095         """
0096         ## In Point of layer. Sets the initial frame of the layer.
0097         self.in_point = None
0098         ## Out Point of layer. Sets the final frame of the layer.
0099         self.out_point = None
0100         ## Start Time of layer. Sets the start time of the layer.
0101         self.start_time = 0
0102         ## After Effects Layer Name. Used for expressions.
0103         self.name = None
0104         ## List of Effects
0105         self.effects = None
0106         ## Layer Time Stretching
0107         self.stretch = 1
0108         ## Layer Parent. Uses ind of parent.
0109         self.parent_index = None
0110         ## List of Masks
0111         self.masks = None
0112         ## Blend Mode
0113         self.blend_mode = BlendMode.Normal
0114         ## Matte mode, the layer will inherit the transparency from the layer above
0115         self.matte_mode = None
0116         ## Composition owning the layer, set by add_layer
0117         self.composition = None
0118 
0119     def add_child(self, layer):
0120         if not self.composition or self.index is None:
0121             raise Exception("Must set composition / index first")
0122         self._child_inout_auto(layer)
0123         self.composition.add_layer(layer)
0124         layer.parent_index = self.index
0125         return layer
0126 
0127     def _child_inout_auto(self, layer):
0128         if layer.in_point is None:
0129             layer.in_point = self.in_point
0130         if layer.out_point is None:
0131             layer.out_point = self.out_point
0132 
0133     @property
0134     def parent(self):
0135         if self.parent_index is None:
0136             return None
0137         return self.composition.layer(self.parent_index)
0138 
0139     @parent.setter
0140     def parent(self, layer):
0141         if layer is None:
0142             self.parent_index = None
0143         else:
0144             self.parent_index = layer.index
0145             layer._child_inout_auto(self)
0146 
0147     @property
0148     def children(self):
0149         for layer in self.composition.layers:
0150             if layer.parent_index == self.index:
0151                 yield layer
0152 
0153     @classmethod
0154     def _load_get_class(cls, lottiedict):
0155         if not Layer._classses:
0156             Layer._classses = {
0157                 sc.type: sc
0158                 for sc in Layer.__subclasses__()
0159             }
0160         type_id = lottiedict["ty"]
0161         if type_id not in Layer._classses:
0162             warnings.warn("Unknown layer type: %s" % type_id)
0163             return Layer
0164         return Layer._classses[type_id]
0165 
0166     def __repr__(self):
0167         return "<%s %s %s>" % (type(self).__name__, self.index, self.name)
0168 
0169     def __str__(self):
0170         return "%s %s" % (
0171             self.name or super().__str__(),
0172             self.index if self.index is not None else ""
0173         )
0174 
0175     def remove(self):
0176         """!
0177         @brief Removes this layer from the componsitin
0178         """
0179         self.composition.remove_layer(self)
0180 
0181 
0182 ## @ingroup Lottie
0183 class NullLayer(Layer):
0184     """!
0185     Layer with no data, useful to group layers together
0186     """
0187     ## %Layer type.
0188     type = 3
0189 
0190     def __init__(self):
0191         Layer.__init__(self)
0192 
0193 
0194 ## @ingroup Lottie
0195 class TextLayer(Layer):
0196     _props = [
0197         LottieProp("data", "t", TextAnimatorData, False),
0198     ]
0199     ## %Layer type.
0200     type = 5
0201 
0202     def __init__(self):
0203         Layer.__init__(self)
0204         ## Text Data
0205         self.data = TextAnimatorData()
0206 
0207 
0208 ## @ingroup Lottie
0209 class ShapeLayer(Layer):
0210     """!
0211     Layer containing ShapeElement objects
0212     """
0213     _props = [
0214         LottieProp("shapes", "shapes", ShapeElement, True),
0215     ]
0216     ## %Layer type.
0217     type = 4
0218 
0219     def __init__(self):
0220         Layer.__init__(self)
0221         ## Shape list of items
0222         self.shapes = [] # ShapeElement
0223 
0224     def add_shape(self, shape):
0225         self.shapes.append(shape)
0226         return shape
0227 
0228     def insert_shape(self, index, shape):
0229         self.shapes.insert(index, shape)
0230         return shape
0231 
0232 
0233 ## @ingroup Lottie
0234 ## @todo SIF I/O
0235 class ImageLayer(Layer):
0236     _props = [
0237         LottieProp("image_id", "refId", str, False),
0238     ]
0239     ## %Layer type.
0240     type = 2
0241 
0242     def __init__(self, image_id=""):
0243         Layer.__init__(self)
0244         ## id pointing to the source image defined on 'assets' object
0245         self.image_id = image_id
0246 
0247 
0248 ## @ingroup Lottie
0249 class PreCompLayer(Layer):
0250     _props = [
0251         LottieProp("reference_id", "refId", str, False),
0252         LottieProp("time_remapping", "tm", Value, False),
0253         LottieProp("width", "w", int, False),
0254         LottieProp("height", "h", int, False),
0255     ]
0256     ## %Layer type.
0257     type = 0
0258 
0259     def __init__(self, reference_id=""):
0260         Layer.__init__(self)
0261         ## id pointing to the source composition defined on 'assets' object
0262         self.reference_id = reference_id
0263         ## Comp's Time remapping
0264         self.time_remapping = None
0265         ## Width
0266         self.width = 512
0267         ## Height
0268         self.height = 512
0269 
0270 
0271 ## @ingroup Lottie
0272 class SolidColorLayer(Layer):
0273     """!
0274     Layer with a solid color rectangle
0275     """
0276     _props = [
0277         LottieProp("color", "sc", str, False),
0278         LottieProp("height", "sh", float, False),
0279         LottieProp("width", "sw", float, False),
0280     ]
0281     ## %Layer type.
0282     type = 1
0283 
0284     def __init__(self, color="", width=512, height=512):
0285         Layer.__init__(self)
0286         ## Color of the layer as a @c \#rrggbb hex
0287         # @todo Convert NVector to string
0288         self.color = color
0289         ## Height of the layer.
0290         self.height = height
0291         ## Width of the layer.
0292         self.width = width