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)