Пример #1
0
 def test_hex_short(self):
     self.assert_nvector_equal(
         parse_color("#abc"),
         NVector(0xa/0xf, 0xb/0xf, 0xc/0xf, 1)
     )
     self.assert_nvector_equal(
         parse_color("#abc"),
         NVector(0xa/0xf, 0xb/0xf, 0xc/0xf, 1)
     )
Пример #2
0
 def test_rgba(self):
     self.assert_nvector_equal(
         parse_color("rgba(12, 34, 56, 0.7)"),
         NVector(12/0xff, 34/0xff, 56/0xff, 0.7)
     );
     self.assert_nvector_equal(
         parse_color("rgba(12%, 34%, 56%, 0.7)"),
         NVector(0.12, 0.34, 0.56, 0.7)
     );
Пример #3
0
 def test_hex_long(self):
     self.assert_nvector_equal(
         parse_color("#abcdef"),
         NVector(0xab/0xff, 0xcd/0xff, 0xef/0xff, 1)
     )
     self.assert_nvector_equal(
         parse_color("#ABCDEF"),
         NVector(0xab/0xff, 0xcd/0xff, 0xef/0xff, 1)
     )
Пример #4
0
 def test_current(self):
     self.assert_nvector_equal(
         parse_color("currentColor", NVector(0.1, 0.2, 0.3, 0.4)),
         NVector(0.1, 0.2, 0.3, 0.4)
     );
     self.assert_nvector_equal(
         parse_color("inherit", NVector(0.1, 0.2, 0.3, 0.4)),
         NVector(0.1, 0.2, 0.3, 0.4)
     );
Пример #5
0
    def test_inkscape_center(self):
        parser = SvgParser()
        element = ElementTree.Element("g")
        group = objects.Rect(NVector(100, 200), NVector(300, 400))
        dest_transform = objects.Transform()

        element.attrib[parser.qualified("inkscape", "transform-center-x")] = 0
        element.attrib[parser.qualified("inkscape", "transform-center-y")] = 0
        parser.parse_transform(element, group, dest_transform)
        self.assert_transform(
            dest_transform,
            anchor_point=NVector(100, 200),
            position=NVector(100, 200),
            scale=NVector(100, 100),
            rotation=0,
            skew_axis=0,
            skew=0,
        )

        element.attrib[parser.qualified("inkscape", "transform-center-x")] = 20
        element.attrib[parser.qualified("inkscape", "transform-center-y")] = -30
        parser.parse_transform(element, group, dest_transform)
        self.assert_transform(
            dest_transform,
            anchor_point=NVector(120, 230),
            position=NVector(120, 230),
            scale=NVector(100, 100),
            rotation=0,
            skew_axis=0,
            skew=0,
        )
Пример #6
0
def get_fill(obj, ro):
    # TODO animation
    fillc = obj.active_material.diffuse_color
    fill = lottie.objects.Fill(NVector(*fillc[:-1]))
    fill.name = obj.active_material.name
    fill.opacity.value = fillc[-1] * 100
    return fill
Пример #7
0
class RenderOptions:
    scene: bpy.types.Scene
    line_width: float = 0
    camera_angles: NVector = NVector(0, 0, 0)

    @property
    def camera(self):
        return scene.camera

    def vector_to_camera_norm(self, vector):
        return NVector(*bpy_extras.object_utils.world_to_camera_view(
            self.scene, self.scene.camera, vector))

    def vpix3d(self, vector):
        v3d = self.vector_to_camera_norm(vector)
        v3d.x *= self.scene.render.resolution_x
        v3d.y *= -self.scene.render.resolution_y
        return v3d

    def vpix(self, vector):
        v2d = self.vpix3d(vector)
        v2d.components.pop()
        return v2d

    def vpix3d_r(self, obj, vector):
        return (self.vpix3d(obj.matrix_world @ vector))

    def vpix_r(self, obj, vector):
        v2d = self.vpix3d_r(obj, vector)
        v2d.components.pop()
        return v2d
Пример #8
0
def context_to_tgs(context):
    scene = context.scene
    root = context.view_layer.layer_collection
    initial_frame = scene.frame_current
    try:
        animation = lottie.objects.Animation()
        animation.in_point = scene.frame_start
        animation.out_point = scene.frame_end
        animation.frame_rate = scene.render.fps
        animation.width = scene.render.resolution_x
        animation.height = scene.render.resolution_y
        animation.name = scene.name
        layer = animation.add_layer(lottie.objects.ShapeLayer())

        ro = RenderOptions(scene)
        if scene.render.use_freestyle:
            ro.line_width = scene.render.line_thickness
        else:
            ro.line_width = 0
        ro.camera_angles = NVector(
            *scene.camera.rotation_euler) * 180 / math.pi

        collection_to_group(root, layer, ro)
        adjust_animation(scene, animation, ro)

        return animation
    finally:
        scene.frame_set(initial_frame)
Пример #9
0
 def test_named(self):
     self.assert_nvector_equal(
         parse_color("transparent"),
         NVector(0, 0, 0, 0)
     );
     self.assert_nvector_equal(
         parse_color("red"),
         NVector(1, 0, 0, 1)
     );
     self.assert_nvector_equal(
         parse_color("lime"),
         NVector(0, 1, 0, 1)
     );
     self.assert_nvector_equal(
         parse_color("blue"),
         NVector(0, 0, 1, 1)
     );
Пример #10
0
    def test_multi_trans(self):
        parser = SvgParser()
        element = ElementTree.Element("g")
        group = objects.Rect(NVector(100, 200), NVector(300, 400))
        dest_transform = objects.Transform()

        element.attrib["transform"] = "scale(0.7, 0.5) rotate(45) translate(12, 34)"
        parser.parse_transform(element, group, dest_transform)
        self.assert_transform(
            dest_transform,
            anchor_point=NVector(0, 0),
            position=NVector(12, 34),
            scale=NVector(70, 50),
            rotation=45,
            skew_axis=0,
            skew=0,
        )
Пример #11
0
def curve_apply_material(obj, g, ro):
    if obj.data.fill_mode != "NONE":
        g.add_shape(get_fill(obj, ro))

    if ro.line_width > 0:
        # TODO animation
        strokec = obj.active_material.line_color
        stroke = lottie.objects.Stroke(NVector(*strokec[:-1]), ro.line_width)
        stroke.opacity.value = fillc[-1] * 100
        g.add_shape(stroke)
Пример #12
0
    def test_matrix(self):
        parser = SvgParser()
        element = ElementTree.Element("g")
        group = objects.Rect(NVector(100, 200), NVector(300, 400))
        dest_transform = objects.Transform()

        m = TransformMatrix()
        m.scale(0.7, 0.5)
        m.rotate(-math.pi/4)
        m.translate(12, 34)
        element.attrib["transform"] = m.to_css_2d()
        parser.parse_transform(element, group, dest_transform)
        self.assert_transform(
            dest_transform,
            anchor_point=NVector(0, 0),
            position=NVector(12, 34),
            scale=NVector(70, 50),
            rotation=45,
            skew_axis=0,
            skew=0,
        )
Пример #13
0
    def assert_convert(self, comps, expect, mode, expect_rt=None):
        color = self.color(*comps)
        conv = color.converted(mode)
        self.assertEqual(
            conv.mode, mode, "%s -> %s has the wrong color space: %s" %
            (self.color_mode, mode, conv.mode))
        self._veq(
            conv, NVector(*expect),
            "%s -> %s has the wrong result: %s (expected %s)" %
            (self.color_mode, mode, conv, expect))

        conv.convert(self.color_mode)
        self.assertEqual(conv.mode, self.color_mode)
        if expect_rt is None:
            expect_rt = color

        self._veq(
            conv, expect_rt, "%s -> %s round trip failed: %s (expected %s)" %
            (self.color_mode, mode, conv, expect_rt))
Пример #14
0
                 "lib"))
from lottie.utils import script
from lottie import objects
from lottie import NVector, Color

an = objects.Animation(80)

precomp = objects.Precomp("myid", an)

# Define stuff in the precomposition (a circle moving left to right)
layer = objects.ShapeLayer()
precomp.add_layer(layer)
layer.out_point = 60

circle = layer.add_shape(objects.Ellipse())
circle.size.value = NVector(100, 100)
circle.position.add_keyframe(0, NVector(-50, 50))
circle.position.add_keyframe(60, NVector(512 + 50, 50))

fill = layer.add_shape(objects.Fill())
fill.color.add_keyframe(0, Color(1, 1, 0))
fill.color.add_keyframe(60, Color(1, 0, 0))

# plays the precomp as it is
pcl0 = an.add_layer(objects.PreCompLayer("myid"))

# plays the precomp, offset in time by 20 frames and in space by 100 pixels
pcl1 = an.add_layer(objects.PreCompLayer("myid"))
pcl1.start_time = 20
pcl1.transform.position.value = NVector(0, 100)
Пример #15
0
stroke.width.value = 10

g2 = layer.add_shape(objects.Group())

circle = g2.add_shape(objects.Ellipse())
circle.size.value = Point(200, 200)
circle.position.value = Point(128 + 256, 256)

fill = g2.add_shape(objects.GradientFill())
fill.gradient_type = objects.GradientType.Radial
fill.start_point.value = Point(128 + 256, 256)
fill.end_point.value = Point(128 + 256 + 100, 256)
fill.colors.set_stops([(0, Color(1, 0, 0)), (1, Color(1, 1, 0))])
#fill.highlight_length.add_keyframe(0, -50)
#fill.highlight_length.add_keyframe(30, 50)
#fill.highlight_length.add_keyframe(59, -50)
#fill.highlight_angle.value = 45
fill.highlight_length.value = 90

g3 = layer.add_shape(objects.Group())
circle = g3.add_shape(objects.Ellipse())
circle.size.value = Point(100, 100)
circle.position.value = Point(128, 356)
fill = g3.add_shape(objects.GradientFill())
fill.start_point.value = Point(100, 0)
fill.end_point.value = Point(200, 0)
fill.colors.set_stops([(0, NVector(1, 0, 0, 1)), (0.5, NVector(1, .5, 0, 1)),
                       (1, NVector(1, 1, 0, 0))])

script.script_main(an)
Пример #16
0
 def test_sanitize_anim(self):
     an = objects.Animation()
     nl = an.add_layer(objects.NullLayer())
     nl.transform.scale.add_keyframe(0, NVector(50, 50))
     nl.transform.scale.add_keyframe(60, NVector(200, 200))
     nl.transform.scale.keyframes[-1].start = None
     an.width = 128
     an.height = 256
     an.frame_rate = 69
     an.tgs_sanitize()
     self.assertEqual(
         an.to_dict(), {
             "ip":
             0,
             "op":
             60,
             "fr":
             60,
             "w":
             512,
             "h":
             512,
             "ddd":
             0,
             "v":
             objects.Animation._version,
             "layers": [
                 {
                     "ty": 3,
                     "ks": {
                         "a": {
                             "a": 0,
                             "k": [0, 0]
                         },
                         "p": {
                             "a": 0,
                             "k": [0, 0]
                         },
                         "s": {
                             "a":
                             1,
                             "k": [
                                 {
                                     "s": [100, 100],
                                     "e": [400, 400],
                                     "t": 0,
                                     "o": {
                                         "x": [0],
                                         "y": [0]
                                     },
                                     "i": {
                                         "x": [1],
                                         "y": [1]
                                     },
                                 },
                                 {
                                     "t": 60,
                                 },
                             ]
                         },
                         "r": {
                             "a": 0,
                             "k": 0
                         },
                         "o": {
                             "a": 0,
                             "k": 100
                         },
                         "sk": {
                             "a": 0,
                             "k": 0
                         },
                         "sa": {
                             "a": 0,
                             "k": 0
                         },
                     },
                     "ao": 0,
                     "ddd": 0,
                     "st": 0,
                     "sr": 1,
                     "bm": 0,
                     "ind": 0,
                     "ip": 0,
                     "op": 60,
                 },
             ],
             "assets": [],
         })
Пример #17
0
def gpencil_to_shape(obj, parent, ro):
    # Object / GreasePencil
    gpen = parent.add_shape(lottie.objects.Group())
    gpen.name = obj.name

    animated = AnimationWrapper(obj.data)
    # GPencilLayer
    for layer in reversed(obj.data.layers):
        if layer.hide:
            continue
        glay = gpen.add_shape(lottie.objects.Group())
        glay.name = layer.info
        opacity = animated.property('layers["%s"].opacity' % layer.info)
        glay.transform.opacity = opacity.to_lottie_prop(lambda x: x * 100)

        gframe = None
        # GPencilFrame
        for frame in layer.frames:
            if gframe:
                if not gframe.transform.opacity.animated:
                    gframe.transform.opacity.add_keyframe(
                        0, 100, lottie.objects.easing.Jump())
                gframe.transform.opacity.add_keyframe(frame.frame_number, 0)

            gframe = glay.add_shape(lottie.objects.Group())
            gframe.name = "frame %s" % frame.frame_number
            if frame.frame_number != 0:
                gframe.transform.opacity.add_keyframe(
                    0, 0, lottie.objects.easing.Jump())
                gframe.transform.opacity.add_keyframe(frame.frame_number, 100)

            # GPencilStroke
            for stroke in reversed(frame.strokes):
                gstroke = gframe.add_shape(lottie.objects.Group())

                path = gstroke.add_shape(lottie.objects.Path())
                path.shape.value.closed = stroke.draw_cyclic
                pressure = 0
                for p in stroke.points:
                    add_point_to_poly(path.shape.value, p, ro, obj)
                    pressure += p.pressure
                pressure /= len(stroke.points)

                # Material
                matp = obj.data.materials[stroke.material_index]
                # TODO Gradients / animations
                # MaterialGPencilStyle
                material = matp.grease_pencil

                if material.show_fill:
                    fill_sh = gstroke.add_shape(lottie.objects.Fill())
                    fill_sh.name = matp.name
                    fill_sh.color.value = NVector(*material.fill_color[:-1])
                    fill_sh.opacity.value = material.fill_color[-1] * 100

                if material.show_stroke:
                    stroke_sh = lottie.objects.Stroke()
                    gstroke.add_shape(stroke_sh)
                    stroke_sh.name = matp.name
                    if stroke.end_cap_mode == "ROUND":
                        stroke_sh.line_cap = lottie.objects.LineCap.Round
                    elif stroke.end_cap_mode == "FLAT":
                        stroke_sh.line_cap = lottie.objects.LineCap.Butt
                    stroke_w = stroke.line_width * pressure * obj.data.pixel_factor
                    if obj.data.stroke_thickness_space == "WORLDSPACE":
                        # TODO do this properly
                        stroke_w /= 9
                    stroke_sh.width.value = stroke_w
                    stroke_sh.color.value = NVector(*material.color[:-1])
                    stroke_sh.opacity.value = material.color[-1] * 100

    return gpen
Пример #18
0
star.inner_radius.value = 20
star.outer_radius.value = 50
star.position.value = Point(50, 50)
star_layer.add_shape(objects.Fill(Color(1, 1, 0)))
star_layer.add_shape(objects.Stroke(Color(0, 0, 0), 5))
star_layer.transform.anchor_point = star.position
star_layer.transform.position.value = Point(50, 256)
star_layer.transform.rotation.add_keyframe(0, 0)
star_layer.transform.rotation.add_keyframe(last_frame, -360)


circle_layer = objects.ShapeLayer()
an.add_layer(circle_layer)
circle_layer.parent = base
circle = circle_layer.add_shape(objects.Ellipse())
circle.size.value = NVector(100, 100)
circle_layer.add_shape(objects.Fill(Color(1, 0, 0)))
circle_layer.add_shape(objects.Stroke(Color(0, 0, 0), 5))
circle_layer.transform.position.add_keyframe(0, Point(256, 512-50))
circle_layer.transform.position.add_keyframe(last_frame/2, Point(256, 50))
circle_layer.transform.position.add_keyframe(last_frame, Point(256, 512-50))


scl = base.add_child(objects.SolidColorLayer("#0000ff"))
scl.transform.scale.value.x *= 0.2
scl.transform.position.value.x = 205


star_background = star_layer.add_child(objects.SolidColorLayer("#0000ff", 100, 100))

Пример #19
0
def _parse_color(color):
    # Inkscape colors
    if re.match(r"^[0-9a-fA-F]{8}$", color):
        return NVector(*(int(color[i:i + 2], 16) / 0xff
                         for i in range(0, 8, 2)))
    return parse_color(color)
Пример #20
0
 def vector_to_camera_norm(self, vector):
     return NVector(*bpy_extras.object_utils.world_to_camera_view(
         self.scene, self.scene.camera, vector))
Пример #21
0
    def test_hsla(self):
        self.assert_nvector_equal(
            parse_color("hsla(0, 100%, 50%, 0.7)"),
            NVector(1, 0, 0, 0.7)
        );
        self.assert_nvector_equal(
            parse_color("hsla(60, 100%, 50%, 0.7)"),
            NVector(1, 1, 0, 0.7)
        );
        self.assert_nvector_equal(
            parse_color("hsla(120, 100%, 50%, 0.7)"),
            NVector(0, 1, 0, 0.7)
        );
        self.assert_nvector_equal(
            parse_color("hsla(180, 100%, 50%, 0.7)"),
            NVector(0, 1, 1, 0.7)
        );
        self.assert_nvector_equal(
            parse_color("hsla(240, 100%, 50%, 0.7)"),
            NVector(0, 0, 1, 0.7)
        );
        self.assert_nvector_equal(
            parse_color("hsla(300, 100%, 50%, 0.7)"),
            NVector(1, 0, 1, 0.7)
        );
        self.assert_nvector_equal(
            parse_color("hsla(360, 100%, 50%, 0.7)"),
            NVector(1, 0, 0, 0.7)
        );

        self.assert_nvector_equal(
            parse_color("hsla(120, 100%, 0%, 0.7)"),
            NVector(0, 0, 0, 0.7)
        );
        self.assert_nvector_equal(
            parse_color("hsla(120, 100%, 100%, 0.7)"),
            NVector(1, 1, 1, 0.7)
        );
        self.assert_nvector_equal(
            parse_color("hsla(120, 100%, 25%, 0.7)"),
            NVector(0, 0.5, 0, 0.7)
        );
        self.assert_nvector_equal(
            parse_color("hsla(120, 75%, 75%, 0.7)"),
            NVector(0.5625, 0.9375, 0.5625, 0.7)
        );
Пример #22
0
 def to_vector(self):
     return NVector(*(v for k, v in sorted(self.value.items())))
Пример #23
0
last_frame = 180
an = objects.Animation(last_frame)

layer = objects.ShapeLayer()
an.add_layer(layer)
layer.auto_orient = True

group = layer.add_shape(objects.Group())
star = objects.Star()
star.inner_radius.value = 20
star.outer_radius.value = 50
star.position.value = Point(0, 0)
group.add_shape(star)

group.add_shape(objects.Ellipse(NVector(0, 35), NVector(16, 16)))

layer.add_shape(objects.Fill(Color(1, 1, 0)))

tl = 120
layer.transform.position.add_keyframe(last_frame / 4 * 0,
                                      Point(+50, 256),
                                      out_tan=NVector(0, -tl),
                                      in_tan=NVector(-tl, 0))
layer.transform.position.add_keyframe(last_frame / 4 * 1,
                                      Point(256, +50),
                                      out_tan=NVector(+tl, 0),
                                      in_tan=NVector(0, -tl))
layer.transform.position.add_keyframe(last_frame / 4 * 2,
                                      Point(462, 256),
                                      out_tan=NVector(0, +tl),