Files
2026-03-01 21:36:54 +08:00

322 lines
8.3 KiB
Python

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),
]