mirror of
https://github.com/OpenVGLab/OmniLottie.git
synced 2026-09-17 07:36:27 +00:00
Initial Commit
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
from xml.dom import minidom
|
||||
import enum
|
||||
from lottie.parsers.sif.sif.core import TypeDescriptor, ObjectRegistry, SifNodeMeta, FrameTime
|
||||
from lottie.parsers.sif.xml.utils import xml_child_elements, xml_first_element_child
|
||||
|
||||
|
||||
class SifAstNode:
|
||||
_subclasses = None
|
||||
_tag = None
|
||||
|
||||
@staticmethod
|
||||
def from_dom(xml: minidom.Element, param: TypeDescriptor, registry: ObjectRegistry):
|
||||
if xml.tagName == param.typename:
|
||||
return SifValue.from_dom(xml, param, registry)
|
||||
|
||||
xmltype = xml.getAttribute("type")
|
||||
if xmltype != param.typename and xmltype != "weighted_" + param.typename:
|
||||
raise ValueError("Invalid type %s (should be %s)" % (xmltype, param.typename))
|
||||
|
||||
return SifAstNode.ast_node_types()[xml.tagName].from_dom(xml, param, registry)
|
||||
|
||||
@staticmethod
|
||||
def ast_node_types():
|
||||
if SifAstNode._subclasses is None:
|
||||
from . import nodes
|
||||
SifAstNode._subclasses = {}
|
||||
SifAstNode._gather_ast_types(SifAstNode)
|
||||
return SifAstNode._subclasses
|
||||
|
||||
@staticmethod
|
||||
def _gather_ast_types(cls):
|
||||
for subcls in cls.__subclasses__():
|
||||
if subcls._tag:
|
||||
SifAstNode._subclasses[subcls._tag] = subcls
|
||||
SifAstNode._gather_ast_types(subcls)
|
||||
|
||||
def _prepare_to_dom(self, dom: minidom.Document, param: TypeDescriptor):
|
||||
element = dom.createElement(self._tag)
|
||||
element.setAttribute("type", param.typename)
|
||||
return element
|
||||
|
||||
|
||||
class SifValue(SifAstNode):
|
||||
def __init__(self, value=None):
|
||||
self.value = value
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s %r>" % (self.__class__.__name__, self.value)
|
||||
|
||||
@classmethod
|
||||
def from_dom(cls, xml: minidom.Element, param: TypeDescriptor, registry: ObjectRegistry):
|
||||
return SifValue(param.value_from_xml_element(xml, registry))
|
||||
|
||||
def to_dom(self, dom: minidom.Document, param: TypeDescriptor):
|
||||
return param.value_to_xml_element(self.value, dom)
|
||||
|
||||
|
||||
class Interpolation(enum.Enum):
|
||||
Auto = "auto"
|
||||
Linear = "linear"
|
||||
Clamped = "clamped"
|
||||
Ease = "halt"
|
||||
Constant = "constant"
|
||||
|
||||
|
||||
class SifKeyframe:
|
||||
def __init__(self, value, time: FrameTime, before=Interpolation.Clamped, after=Interpolation.Clamped):
|
||||
self.value = value
|
||||
self.time = time
|
||||
self.before = before
|
||||
self.after = after
|
||||
|
||||
@classmethod
|
||||
def from_dom(cls, xml: minidom.Element, param: TypeDescriptor, registry: ObjectRegistry):
|
||||
return cls(
|
||||
param.value_from_xml_element(xml_first_element_child(xml), registry),
|
||||
FrameTime.parse_string(xml.getAttribute("time"), registry),
|
||||
Interpolation(xml.getAttribute("before")),
|
||||
Interpolation(xml.getAttribute("after"))
|
||||
)
|
||||
|
||||
def to_dom(self, dom: minidom.Document, param: TypeDescriptor):
|
||||
element = dom.createElement("waypoint")
|
||||
element.setAttribute("time", str(self.time))
|
||||
element.setAttribute("before", self.before.value)
|
||||
element.setAttribute("after", self.after.value)
|
||||
element.appendChild(param.value_to_xml_element(self.value, dom))
|
||||
return element
|
||||
|
||||
def __repr__(self):
|
||||
return "<SifKeyframe %s %s>" % (self.time, self.value)
|
||||
|
||||
|
||||
class SifAnimated(SifAstNode):
|
||||
_tag = "animated"
|
||||
|
||||
def __init__(self):
|
||||
self.keyframes = []
|
||||
|
||||
@classmethod
|
||||
def from_dom(cls, xml: minidom.Element, param: TypeDescriptor, registry: ObjectRegistry):
|
||||
obj = SifAnimated()
|
||||
for waypoint in xml_child_elements(xml, "waypoint"):
|
||||
obj.keyframes.append(SifKeyframe.from_dom(waypoint, param, registry))
|
||||
return obj
|
||||
|
||||
def to_dom(self, dom: minidom.Document, param: TypeDescriptor):
|
||||
element = self._prepare_to_dom(dom, param)
|
||||
for kf in self.keyframes:
|
||||
element.appendChild(kf.to_dom(dom, param))
|
||||
return element
|
||||
|
||||
def add_keyframe(self, *args, **kwargs):
|
||||
if not kwargs and len(args) == 1 and isinstance(args[0], SifKeyframe):
|
||||
keyframe = args[0]
|
||||
else:
|
||||
keyframe = SifKeyframe(*args, **kwargs)
|
||||
|
||||
self.keyframes.append(keyframe)
|
||||
return keyframe
|
||||
Reference in New Issue
Block a user