1
$\begingroup$

I have the following code to draw a black grease pencil line segment, from the points [0, 0, 0] to [1, 1, 0]:

from typing import Tuple

from bpy.types import GreasePencil, GPencilLayer, GPencilFrame, GPencilStroke
import bpy


def create_gp(gp_data: GreasePencil, name) -> GreasePencil:
    if name not in bpy.context.scene.objects:
        gp_obj = bpy.data.objects.new(name, gp_data)
        bpy.context.scene.objects[-1].name = name
        bpy.context.scene.collection.objects.link(gp_obj)

    return bpy.context.scene.objects.get(name)


def create_gp_layer(gp_obj, layer_name, clear_layer) -> GPencilLayer:
    # Get grease pencil layer or create one if none exists
    if layer_name in gp_obj.data.layers:
        gp_layer = gp_obj.data.layers.get(layer_name)
    else:
        gp_layer = gp_obj.data.layers.new(layer_name, set_active=True)

    if clear_layer:
        gp_layer.clear()

    return gp_layer


def init_gp(name) -> Tuple[GreasePencil, GreasePencil]:
    gp_data = bpy.data.grease_pencils.new(name)
    gp_obj = create_gp(gp_data, name)

    return gp_data, gp_obj


def stroke_polyline(gp_frame: GPencilFrame, vertices, line_width) -> GPencilStroke:
    gp_stroke = gp_frame.strokes.new()
    gp_stroke.points.add(len(vertices))

    for ix, vertex in enumerate(vertices):
        gp_stroke.points[ix].co = vertex

    gp_stroke.line_width = line_width
    return gp_stroke


def create_gp_material(name: str, color) -> bpy.types.Material:
    gp_mat = bpy.data.materials.new(name)
    bpy.data.materials.create_gpencil_data(gp_mat)
    gp_mat.grease_pencil.color = color

    return gp_mat


gp_dat, gp_obj = init_gp("TestPencil")
gp_layer = create_gp_layer(gp_obj, "TestLayer", True)
gp_frame = gp_layer.frames.new(0)
gp_mat = create_gp_material("BlackLine", [0., 0., 0., 1.])
gp_dat.materials.append(gp_mat)
gp_stroke = stroke_polyline(gp_frame, [[0, 0, 0], [1, 1, 0]], 10)

print("Success!")

It produces the following output:

enter image description here

So far, so good. Now, I want to draw lots of different things, on many different layers, each with many different frames, etc. This will require proper management of the grease pencil objects, but since I put together this code by scrounging around on the internet, I do not understand some of the central concepts.

  1. What is the difference between gp_dat, and gp_obj? Both have type GreasePencil, so why is it that gp_dat has a materials attribute, but gp_obj does not? Why do they need to be linked together by the bpy.context.scene.collection.objects.link(gp_obj) instruction? (I learned I must do this from: Creating a Grease Pencil Material in Blender 2.8)

  2. Assuming I have only one Blender scene, how many gp_dat/gp_obj pairs should one create? I think I could do all my drawing using only one grease pencil object, with many associated materials. (Although, I haven't yet figured out how to assign a particular material to a drawing instruction.) So, under what circumstances will I need to create multiple grease pencil objects?

$\endgroup$
1
  • $\begingroup$ gp_data is the data of the gp_obj, and you are linking the object to the scene and not to the data. you can get the material from obj with bpy.context.selected_objects[0].data.materials[0] $\endgroup$ – Alex bries Nov 4 '20 at 9:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.