mirror of
https://github.com/OpenVGLab/OmniLottie.git
synced 2026-09-17 15:46:26 +00:00
161 lines
5.9 KiB
Python
161 lines
5.9 KiB
Python
from xml.dom import minidom
|
|||
|
|
import copy
|
||
|
|
import enum
|
||
|
|
|
||
|
|
from .core_nodes import XmlDescriptor, XmlSimpleElement, ValueReference
|
||
|
|
from .utils import *
|
||
|
|
from lottie.nvector import NVector
|
||
|
|
from lottie.parsers.sif.ast_impl.base import SifAstNode, SifValue
|
||
|
|
from lottie.parsers.sif.sif.core import ObjectRegistry, TypeDescriptor, noop
|
||
|
|
|
||
|
|
|
||
|
|
class XmlAnimatable(XmlDescriptor):
|
||
|
|
def __init__(self, name, typename, default=None, type_wrapper=noop):
|
||
|
|
super().__init__(name)
|
||
|
|
self.type = TypeDescriptor(typename, default, type_wrapper)
|
||
|
|
|
||
|
|
def from_xml(self, obj, parent: minidom.Element, registry: ObjectRegistry, param: TypeDescriptor = None):
|
||
|
|
cn = xml_first_element_child(parent, self.name)
|
||
|
|
if cn:
|
||
|
|
value = SifAstNode.from_dom(xml_first_element_child(cn), self.type_for(param), registry)
|
||
|
|
else:
|
||
|
|
value = self.default()
|
||
|
|
|
||
|
|
setattr(obj, self.att_name, value)
|
||
|
|
|
||
|
|
def to_xml(self, obj, parent: minidom.Element, dom: minidom.Document, type: TypeDescriptor = None):
|
||
|
|
value = getattr(obj, self.att_name)
|
||
|
|
if isinstance(value, SifValue) and isinstance(value.value, ValueReference):
|
||
|
|
parent.setAttribute(self.name, ":" + value.value.id)
|
||
|
|
return
|
||
|
|
param = parent.appendChild(dom.createElement(self.name))
|
||
|
|
param.appendChild(value.to_dom(dom, self.type_for(type)))
|
||
|
|
return param
|
||
|
|
|
||
|
|
def from_python(self, value):
|
||
|
|
if not isinstance(value, SifAstNode):
|
||
|
|
raise ValueError("%s isn't a valid value for %s" % (value, self.name))
|
||
|
|
return value
|
||
|
|
|
||
|
|
def default(self):
|
||
|
|
return SifValue(copy.deepcopy(self.type.default_value))
|
||
|
|
|
||
|
|
def type_for(self, param: TypeDescriptor):
|
||
|
|
if param is not None and self.type.typename == "_recurse":
|
||
|
|
return param
|
||
|
|
return self.type
|
||
|
|
|
||
|
|
|
||
|
|
class XmlParam(XmlDescriptor):
|
||
|
|
def __init__(self, name, typename, default=None, type_wrapper=noop, static=False):
|
||
|
|
super().__init__(name)
|
||
|
|
self.type = TypeDescriptor(typename, default, type_wrapper)
|
||
|
|
self.static = static
|
||
|
|
|
||
|
|
def _def(self):
|
||
|
|
from ..api import Def
|
||
|
|
return Def
|
||
|
|
|
||
|
|
def from_xml(self, obj, parent: minidom.Element, registry: ObjectRegistry):
|
||
|
|
for cn in xml_child_elements(parent, "param"):
|
||
|
|
if cn.getAttribute("name") == self.name:
|
||
|
|
use = cn.getAttribute("use")
|
||
|
|
if use:
|
||
|
|
value = registry.get_object(use)
|
||
|
|
else:
|
||
|
|
value_node = xml_first_element_child(cn)
|
||
|
|
if self.static:
|
||
|
|
value = self.type.value_from_xml_element(value_node, registry)
|
||
|
|
else:
|
||
|
|
value = SifAstNode.from_dom(value_node, self.type, registry)
|
||
|
|
break
|
||
|
|
else:
|
||
|
|
value = self.default()
|
||
|
|
|
||
|
|
setattr(obj, self.att_name, value)
|
||
|
|
|
||
|
|
def to_xml(self, obj, parent: minidom.Element, dom: minidom.Document):
|
||
|
|
param = parent.appendChild(dom.createElement("param"))
|
||
|
|
param.setAttribute("name", self.name)
|
||
|
|
value = getattr(obj, self.att_name)
|
||
|
|
if isinstance(value, self._def()):
|
||
|
|
param.setAttribute("use", ":" + value.id)
|
||
|
|
else:
|
||
|
|
if self.static:
|
||
|
|
elem = self.type.value_to_xml_element(value, dom)
|
||
|
|
else:
|
||
|
|
elem = value.to_dom(dom, self.type)
|
||
|
|
param.appendChild(elem)
|
||
|
|
return param
|
||
|
|
|
||
|
|
def from_python(self, value):
|
||
|
|
if self.static:
|
||
|
|
return self.type.type_wrapper(value)
|
||
|
|
if not isinstance(value, (SifAstNode, self._def())):
|
||
|
|
raise ValueError("%s isn't a valid value for %s" % (value, self.name))
|
||
|
|
return value
|
||
|
|
|
||
|
|
def default(self):
|
||
|
|
if self.static:
|
||
|
|
return copy.deepcopy(self.type.default_value)
|
||
|
|
return SifValue(copy.deepcopy(self.type.default_value))
|
||
|
|
|
||
|
|
|
||
|
|
class XmlDynamicListParam(XmlDescriptor):
|
||
|
|
_tag = "dynamic_list"
|
||
|
|
|
||
|
|
def __init__(self, name, typename, att_name=None):
|
||
|
|
super().__init__(name)
|
||
|
|
self.type = TypeDescriptor(typename)
|
||
|
|
if att_name is not None:
|
||
|
|
self.att_name = att_name
|
||
|
|
|
||
|
|
def to_xml(self, obj, parent: minidom.Element, dom: minidom.Document):
|
||
|
|
param = parent.appendChild(dom.createElement("param"))
|
||
|
|
param.setAttribute("name", self.name)
|
||
|
|
dyl = param.appendChild(dom.createElement(self._tag))
|
||
|
|
dyl.setAttribute("type", self.type.typename)
|
||
|
|
values = getattr(obj, self.att_name)
|
||
|
|
for val in values:
|
||
|
|
entry = dyl.appendChild(dom.createElement("entry"))
|
||
|
|
entry.appendChild(self._value_to_dom(val, dom))
|
||
|
|
|
||
|
|
def _value_to_dom(self, val, dom: minidom.Document):
|
||
|
|
return val.to_dom(dom, self.type)
|
||
|
|
|
||
|
|
def from_xml(self, obj, parent: minidom.Element, registry: ObjectRegistry):
|
||
|
|
values = []
|
||
|
|
|
||
|
|
for cn in xml_child_elements(parent, "param"):
|
||
|
|
if cn.getAttribute("name") == self.name:
|
||
|
|
list = xml_first_element_child(cn)
|
||
|
|
if list.getAttribute("type") != self.type.typename:
|
||
|
|
raise ValueError(
|
||
|
|
"Wrong type for %s: got %s instead of %s" %
|
||
|
|
(self.name, self.type.typename, list.getAttribute("type"))
|
||
|
|
)
|
||
|
|
for entry in xml_child_elements(list, "entry"):
|
||
|
|
values.append(self._value_from_dom(xml_first_element_child(entry), registry))
|
||
|
|
break
|
||
|
|
|
||
|
|
setattr(obj, self.att_name, values)
|
||
|
|
|
||
|
|
def _value_from_dom(self, element, registry):
|
||
|
|
return SifAstNode.from_dom(element, self.type, registry)
|
||
|
|
|
||
|
|
def from_python(self, value):
|
||
|
|
return value
|
||
|
|
|
||
|
|
def default(self):
|
||
|
|
return []
|
||
|
|
|
||
|
|
|
||
|
|
class XmlStaticListParam(XmlDynamicListParam):
|
||
|
|
_tag = "static_list"
|
||
|
|
|
||
|
|
def _value_to_dom(self, val, dom: minidom.Document):
|
||
|
|
return self.type.value_to_xml_element(val, dom)
|
||
|
|
|
||
|
|
def _value_from_dom(self, element: minidom.Element, registry: ObjectRegistry):
|
||
|
|
return self.type.value_from_xml_element(element, registry)
|