from xml.dom import minidom import enum from lottie.nvector import NVector from lottie.parsers.sif.ast_impl.base import SifAstNode, TypeDescriptor, ObjectRegistry from lottie.parsers.sif.xml.animatable import XmlAnimatable from lottie.parsers.sif.xml.wrappers import XmlBoneReference, XmlSifElement, XmlList from lottie.parsers.sif.sif.nodes import Segment, WeightedVector, Bline from lottie.parsers.sif.sif.enums import Smooth from lottie.parsers.sif.sif.core import SifNodeMeta, FrameTime class SifAstComplex(SifAstNode, metaclass=SifNodeMeta): _nodes = [] def __init__(self, **kw): for node in self._nodes: node.initialize_object(kw, self) @classmethod def from_dom(cls, xml: minidom.Element, param: TypeDescriptor, registry: ObjectRegistry): outcls = cls.get_class_from_dom(xml, param, registry) instance = outcls() for node in outcls._nodes: node.from_xml(instance, xml, registry) return instance @classmethod def get_class_from_dom(cls, xml: minidom.Element, param: TypeDescriptor, registry: ObjectRegistry): return cls def to_dom(self, dom: minidom.Document, param: TypeDescriptor): element = self._prepare_to_dom(dom, param) for node in self._nodes: node.to_xml(self, element, dom, param) return element class SifAstBoneLink(SifAstComplex): _tag = "bone_link" _nodes = [ XmlBoneReference("bone"), XmlAnimatable("base_value", "vector", NVector(0, 0)), XmlAnimatable("translate", "bool", True), XmlAnimatable("rotate", "bool", True), XmlAnimatable("skew", "bool", True), XmlAnimatable("scale_x", "bool", True), XmlAnimatable("scale_y", "bool", True), ] class SifAstBoneInfluence(SifAstComplex): _tag = "boneinfluence" _nodes = [ # TODO bone_weight_list XmlAnimatable("link", "vector", NVector(0, 0)), ] class SifSegCalcTangent(SifAstComplex): _tag = "segcalctangent" _nodes = [ XmlSifElement("segment", Segment), XmlAnimatable("amount", "real", .5), ] class SifSegCalcVertex(SifAstComplex): _tag = "segcalcvertex" _nodes = [ XmlSifElement("segment", Segment), XmlAnimatable("amount", "real", .5), ] class WeightedAverage(SifAstComplex): _tag = "weighted_average" _nodes = [ XmlList(WeightedVector, "vectors", "entry"), ] def _prepare_to_dom(self, dom: minidom.Document, param: TypeDescriptor): element = dom.createElement(self._tag) element.setAttribute("type", "weighted_vector") return element class SifAdd(SifAstComplex): _tag = "add" _nodes = [ XmlAnimatable("lhs", "_recurse"), XmlAnimatable("rhs", "_recurse"), XmlAnimatable("scalar", "real", 1.), ] class SifAnimatedFile(SifAstComplex): _tag = "animated_file" _nodes = [ XmlAnimatable("filename", "string"), ] class Accuracy(enum.Enum): Rough = 0 Normal = 1 Fine = 2 Extreme = 3 class DerivativeOrder: FirstDerivative = 0 SecondDerivative = 1 class SifDerivative(SifAstComplex): _tag = "derivative" _nodes = [ XmlAnimatable("link", "_recurse"), XmlAnimatable("interval", "real", 0.01), XmlAnimatable("accuracy", "integer", Accuracy.Normal, Accuracy), XmlAnimatable("order", "integer", DerivativeOrder.FirstDerivative, DerivativeOrder), ] class SifDynamic(SifAstComplex): _tag = "dynamic" _nodes = [ XmlAnimatable("tip_static", "vector", NVector(0, 0)), XmlAnimatable("origin", "vector", NVector(0, 0)), XmlAnimatable("force", "vector", NVector(0, 0)), XmlAnimatable("torque", "real", 0.), XmlAnimatable("damping", "real", 0.4), XmlAnimatable("friction", "real", 0.4), XmlAnimatable("spring", "real", 30.), XmlAnimatable("torsion", "real", 30.), XmlAnimatable("mass", "real", 0.3), XmlAnimatable("inertia", "real", 0.3), XmlAnimatable("spring_rigid", "bool", False), XmlAnimatable("torsion_rigid", "bool", False), XmlAnimatable("origin_drags_tip", "bool", True), ] class SifGreyed(SifAstComplex): _tag = "greyed" _nodes = [ XmlAnimatable("link", "_recurse"), ] class SifLinear(SifAstComplex): _tag = "linear" _nodes = [ XmlAnimatable("slope", "vector", NVector(0, 0)), XmlAnimatable("offset", "vector", NVector(0, 0)), ] class SifRadialComposite(SifAstComplex): _tag = "radial_composite" _nodes = [ XmlAnimatable("radius", "real", 0.), XmlAnimatable("theta", "angle", 0.), ] class SifComposite(SifAstComplex): _tag = "composite" @classmethod def get_class_from_dom(cls, xml: minidom.Element, param: TypeDescriptor, registry: ObjectRegistry): type = xml.getAttribute("type") if type == "vector": return SifVectorComposite return None def _prepare_to_dom(self, dom: minidom.Document, param: TypeDescriptor): element = dom.createElement("composite") element.setAttribute("type", param.typename) return element class SifVectorComposite(SifComposite): _type = "vector" _nodes = [ XmlAnimatable("x", "real", 0.), XmlAnimatable("y", "real", 0.), ] class SifRandom(SifAstComplex): _tag = "random" _nodes = [ XmlAnimatable("link", "_recurse"), XmlAnimatable("radius", "real", 0.), XmlAnimatable("seed", "integer", 0), XmlAnimatable("speed", "real", 1.), XmlAnimatable("smooth", "integer", Smooth.Cubic, Smooth), XmlAnimatable("loop", "real", 0.), ] class SifReference(SifAstComplex): _tag = "link" _nodes = [ XmlAnimatable("reference", "_recurse"), ] class SifScale(SifAstComplex): _tag = "scale" _nodes = [ XmlAnimatable("link", "_recurse"), XmlAnimatable("scalar", "real", 1.), ] class SifStep(SifAstComplex): _tag = "step" _nodes = [ XmlAnimatable("link", "_recurse"), XmlAnimatable("duration", "time", FrameTime(1, FrameTime.Unit.Seconds)), XmlAnimatable("start_time", "time", FrameTime(0, FrameTime.Unit.Seconds)), XmlAnimatable("intersection", "real", 0.5), ] class SifSubtract(SifAstComplex): _tag = "subtract" _nodes = [ XmlAnimatable("lhs", "_recurse"), XmlAnimatable("rhs", "_recurse"), XmlAnimatable("scalar", "real", 1.), ] class SifSwitch(SifAstComplex): _tag = "switch" _nodes = [ XmlAnimatable("link_off", "_recurse"), XmlAnimatable("link_on", "_recurse"), XmlAnimatable("switch", "bool", False), ] class SifTimedSwap(SifAstComplex): _tag = "timed_swap" _nodes = [ XmlAnimatable("before", "_recurse"), XmlAnimatable("after", "_recurse"), XmlAnimatable("time", "time", FrameTime(0, FrameTime.Unit.Seconds)), XmlAnimatable("length", "time", FrameTime(0, FrameTime.Unit.Seconds)), ] class SifTimeLoop(SifAstComplex): _tag = "timeloop" _nodes = [ XmlAnimatable("link", "_recurse"), XmlAnimatable("link_time", "time", FrameTime(0, FrameTime.Unit.Seconds)), XmlAnimatable("local_time", "time", FrameTime(0, FrameTime.Unit.Seconds)), XmlAnimatable("duration", "time", FrameTime(0, FrameTime.Unit.Seconds)), ] class SifPower(SifAstComplex): _tag = "power" _nodes = [ XmlAnimatable("base", "real", 1.), XmlAnimatable("power", "real", 1.), XmlAnimatable("epsilon", "real", 0.000001), XmlAnimatable("infinite", "real", 999999.), ] class SifBlineCalcTangent(SifAstComplex): _tag = "blinecalctangent" _nodes = [ XmlSifElement("bline", Bline), XmlAnimatable("loop", "bool", False), XmlAnimatable("amount", "real", 0.5), XmlAnimatable("offset", "angle", 0.), XmlAnimatable("scale", "real", 1.), XmlAnimatable("fixed_length", "bool", False), XmlAnimatable("homogeneous", "bool", False), ] class SifBlineCalcVertex(SifAstComplex): _tag = "blinecalcvertex" _nodes = [ XmlSifElement("bline", Bline), XmlAnimatable("loop", "bool", False), XmlAnimatable("amount", "real", 0.5), XmlAnimatable("homogeneous", "bool", False), ]