1
$\begingroup$

Grease pencil clears all previous strokes when writing a new frame. I want to keep the existing strokes and copy them to the new frame before a new stroke has been drawn.

When drawing in the interface, this can be done by enabling additive drawing. There also seems to be an operator which can copy the current frame to a new frame, but I haven't been able to get it working: frames.copy()

How can I do this?

import bpy
import math
from math import sin, cos

def get_grease_pencil(gpencil_obj_name='GPencil') -> bpy.types.GreasePencil:
    # If not present already, create grease pencil object
    if gpencil_obj_name not in bpy.context.scene.objects:
        bpy.ops.object.gpencil_add(view_align=False, location=(0, 0, 0), type='EMPTY')
    # Get grease pencil object
    gpencil = bpy.context.scene.objects[gpencil_obj_name]
    return gpencil

def get_grease_pencil_layer(gpencil: bpy.types.GreasePencil, gpencil_layer_name='GP_Layer', clear_layer=False) -> bpy.types.GPencilLayer:
    # Get grease pencil layer or create one if none exists
    if gpencil.data.layers and gpencil_layer_name in gpencil.data.layers:
        gpencil_layer = gpencil.data.layers[gpencil_layer_name]
    else:
        gpencil_layer = gpencil.data.layers.new(gpencil_layer_name, set_active=True)
    if clear_layer:
        gpencil_layer.clear() 
    return gpencil_layer

# Util for default behavior merging previous two methods
def init_grease_pencil(gpencil_obj_name='GPencil', gpencil_layer_name='GP_Layer', clear_layer=False) -> bpy.types.GPencilLayer:
    gpencil = get_grease_pencil(gpencil_obj_name)
    gpencil_layer = get_grease_pencil_layer(gpencil, gpencil_layer_name, clear_layer=clear_layer)
    return gpencil_layer

def draw_circle(gp_frame, center: tuple, radius: float, segments: int):

    # Init new stroke
    gp_stroke = gp_frame.strokes.new()
    gp_stroke.display_mode = '3DSPACE'  # allows for editing
    gp_stroke.draw_cyclic = True       # closes the stroke
    gp_stroke.line_width = 300
    # Define stroke geometry
    angle = 2*math.pi/segments  # angle in radians
    gp_stroke.points.add(count=segments)
    for i in range(segments):
        x = center[0] + radius*math.cos(angle*i)
        y = center[1] + radius*math.sin(angle*i)
        z = center[2]
        gp_stroke.points[i].co = (x, y, z)  
    return gp_stroke

def draw_multiple_circles_animated(gp_layer):
    for frame in range(60):
        gp_frame = gp_layer.frames.new(frame)
        radius = sin(frame/30)
        draw_circle(gp_frame, (0, sin(frame/3 ), frame/3), radius, 80)

gp_layer = init_grease_pencil(clear_layer=True, gpencil_layer_name='animLayer')
draw_multiple_circles_animated(gp_layer)
$\endgroup$

1 Answer 1

2
$\begingroup$

I fixed it. This change works nicely!

def draw_multiple_circles_animated(gp_layer):
    gp_frame = gp_layer.frames.new(0)
    for frame in range(60):
        gp_layer.frames.copy(gp_frame)
        radius = sin(frame/30)
        draw_circle(gp_frame, (0, sin(frame/3 ), frame/3), radius, 80)
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .