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 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 TimeLoopLayer(Layer): _layer_type = "timeloop" _nodes = [ XmlParam("z_depth", "real", 0.), XmlParam("link_time", "time", FrameTime(0, FrameTime.Unit.Seconds), static=True), XmlParam("local_time", "time", FrameTime(0, FrameTime.Unit.Seconds), static=True), XmlParam("duration", "time", FrameTime(0, FrameTime.Unit.Seconds), static=True), XmlParam("only_for_positive_duration", "bool", False, static=True), XmlParam("symmetrical", "bool", True, static=True), ]
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 FreeTimeLayer(Layer): _layer_type = "freetime" _nodes = [ XmlParam("z_depth", "real", 0.), XmlParam("time", "time", FrameTime(0, FrameTime.Unit.Seconds)), ]
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")))
class SoundLayer(Layer): _layer_type = "sound" _nodes = [ XmlParam("z_depth", "real", 0.), XmlParam("filename", "string"), XmlParam("delay", "time", FrameTime(0, FrameTime.Unit.Seconds)), XmlParam("volume", "real", 1.), ]
class MotionBlurLayer(Layer): _layer_type = "MotionBlur" _nodes = [ XmlParam("aperture", "time", FrameTime(1, FrameTime.Unit.Seconds)), XmlParam("subsamples_factor", "real", 1.), XmlParam("subsampling_type", "integer", SubsamplingType.Hyperbolic, SubsamplingType), XmlParam("subsample_start", "real", 0.), XmlParam("subsample_end", "real", 1.), ]
class ImportedImageLayer(DrawableLayer): _layer_type = "import" _nodes = [ XmlParam("tl", "vector", NVector(0, 0)), XmlParam("br", "vector", NVector(0, 0)), XmlParam("c", "integer", Smooth.Linear, Smooth), XmlParam("gamma_adjust", "real", 1.), XmlParam("filename", "string"), XmlParam("time_offset", "time", FrameTime(0, FrameTime.Unit.Frame)), ]
class GroupLayerBase(DrawableLayer): _nodes = [ XmlParam("origin", "vector", NVector(0, 0)), XmlParamSif("transformation", AbstractTransform, SifTransform), XmlWrapperParam("canvas", XmlWrapper("canvas", XmlList(Layer))), XmlParam("time_dilation", "real", 1.), XmlParam("time_offset", "time", FrameTime(0, FrameTime.Unit.Frame)), XmlParam("children_lock", "bool", False, static=True), XmlParam("outline_grow", "real", 0.), ] def add_layer(self, layer: Layer): self.layers.append(layer) return layer
class Canvas(SifNode, ObjectRegistry): _nodes = [ XmlAttribute("version"), XmlAttribute("width", float, 512), XmlAttribute("height", float, 512), XmlAttribute("xres", float, 2834.645752), XmlAttribute("yres", float, 2834.645752), XmlAttribute("gamma-r", float, 1.), XmlAttribute("gamma-g", float, 1.), XmlAttribute("gamma-b", float, 1.), XmlAttribute("view-box", NVector), XmlAttribute("antialias", bool, True), XmlAttribute("fps", float, 60), XmlAttribute("begin-time", FrameTime, FrameTime(0, FrameTime.Unit.Frame)), XmlAttribute("end-time", FrameTime, FrameTime(3, FrameTime.Unit.Seconds)), XmlAttribute("bgcolor", NVector, NVector(0, 0, 0, 0)), XmlSimpleElement("name"), XmlMeta("background_first_color", NVector, NVector(0.88, 0.88, 0.88)), XmlMeta("background_rendering", bool, False), XmlMeta("background_second_color", NVector, NVector(0.65, 0.65, 0.65)), XmlMeta("background_size", NVector, NVector(15, 15)), XmlMeta("grid_color", NVector, NVector(0.62, 0.62, 0.62)), XmlMeta("grid_show", bool, False), XmlMeta("grid_size", NVector, NVector(0.25, 0.25)), XmlMeta("grid_snap", bool, False), XmlMeta("guide_color", NVector, NVector(0.4, 0.4, 1)), XmlMeta("guide_show", bool, True), XmlMeta("guide_snap", bool, False), XmlMeta("jack_offset", float, 0), XmlMeta("onion_skin", bool, False), XmlMeta("onion_skin_future", int, 0), XmlMeta("onion_skin_past", int, 1), XmlList(Keyframe), XmlWrapper("defs", XmlList(Def, "defs", None, Def.tags())), XmlWrapper("bones", XmlList(BoneRoot, "bones", None, {"bone", "bone_root"})), XmlList(Layer), ] def __init__(self, **kw): SifNode.__init__(self, **kw) ObjectRegistry.__init__(self) def to_xml(self): dom = minidom.Document() dom.appendChild(self.to_dom(dom)) return dom @classmethod def from_xml_file(cls, xml): if isinstance(xml, str): with open(xml, "r") as file: return cls.from_xml(minidom.parse(file)) return cls.from_xml(minidom.parse(xml)) @classmethod def from_xml_string(cls, xml): return cls.from_xml(minidom.parseString(xml)) @classmethod def from_xml(cls, xml: minidom.Document): obj = cls.from_dom(xml.documentElement, None) xml.unlink() return obj @classmethod def from_dom(cls, xml: minidom.Element, registry: ObjectRegistry = None): instance = cls() for node in cls._nodes: node.from_xml(instance, xml, instance) return instance def time_to_frames(self, time: FrameTime): if time.unit == FrameTime.Unit.Frame: return time.value elif time.unit == FrameTime.Unit.Seconds: return time.value * self.fps def add_layer(self, layer: Layer): self.layers.append(layer) return layer def make_color(self, r, g, b, a=1): """ Applies Gamma to the rgb values """ return NVector( r ** self.gamma_r, g ** self.gamma_g, b ** self.gamma_b, a )
class Keyframe(SifNode): _nodes = [ XmlAttribute("active", bool_str, True), XmlAttribute("time", FrameTime, FrameTime(0, FrameTime.Unit.Frame)), ]