3
$\begingroup$

I would like to pre-define a material for a grease pencil in an addon. However, when a new material is created from python, it is not a grease pencil material (mat.is_grease_pencil = False). It is not possible to set the mat.grease_pencil.color of this material, because this part of the data structure does not exist, etc.

What is the python equivalent of clicking the "New (add a new material)" button when a grease pencil object is active?

# Create a grease pencil object
bpy.ops.object.gpencil_add(type='EMPTY')
bpy.ops.object.mode_set(mode='PAINT_GPENCIL')
gp_obj = bpy.data.objects['GPencil']
bpy.context.view_layer.objects.active = gp_obj

# Create a net material
gp_mat = bpy.data.materials.new("my_gp_material")  # This is not a grease pencil material
gp_mat.grease_pencil.color = [0,1,0,1]  # This is not possible, as mat.grease_pencil is None
gp_obj.data.materials.append(gp_mat)  # Trying to draw after this will crash Blender

Thanks for your help!

$\endgroup$

2 Answers 2

8
$\begingroup$

Use bpy.data.materials.create_gpencil_data(mat) to add grease pencil material settings

import bpy
context = bpy.context
space = context.space_data

# Create material for grease pencil
if "Bright Material" in bpy.data.materials.keys():
    gp_mat = bpy.data.materials["Bright Material"]
else:
    gp_mat = bpy.data.materials.new("Bright Material")

if not gp_mat.is_grease_pencil:
    bpy.data.materials.create_gpencil_data(gp_mat)
    gp_mat.grease_pencil.color = (1, 0, 0.818649, 1)

# Add grease pencil object
gp_data = bpy.data.grease_pencils.new("Bright Pencil")
gp_ob = bpy.data.objects.new("Bright Pencil", gp_data)
context.scene.collection.objects.link(gp_ob)
if space.local_view:
    gp_ob.local_view_set(space, True)

for ob in context.selected_objects:
    ob.select_set(False)
gp_ob.select_set(True)
context.view_layer.objects.active = gp_ob
bpy.ops.object.mode_set(mode='PAINT_GPENCIL')

# Assign the material to the grease pencil for drawing
gp_data.materials.append(gp_mat)

# Draw, using the material defined
bpy.ops.gpencil.draw(wait_for_input=False)
$\endgroup$
0
$\begingroup$

The best solution I have found so far is to create a new grease pencil stroke object, modify its material as desired, then delete the stroke object but keep the material, which can then be assigned to new grease pencil objects, as below.

If a more elegant solution exists, please share!

def get_gp_material():
    # Create a stroke object, modify its material, delete the stroke
    bpy.ops.object.gpencil_add(type='STROKE')
    gp_stroke_obj = bpy.context.object
    stroke_mat = gp_stroke_obj.material_slots[0].material
    stroke_mat.grease_pencil.color = [0,1,0,1]
    stroke_mat.name = "my_gp_material"
    bpy.ops.object.delete()
    del gp_stroke_obj
    return(stroke_mat)

# Get grease pencil material, must be done before creating blank GP object
gp_mat = get_gp_material()
# Add a new grease pencil blank
bpy.ops.object.gpencil_add(type='EMPTY')
# Go into draw mode
bpy.ops.object.mode_set(mode='PAINT_GPENCIL')
# Set the material
gp_obj = bpy.data.objects['GPencil']
gp_obj.data.materials.append(gp_mat)
gp_obj.active_material = gp_mat
# Now ready to draw
$\endgroup$

You must log in to answer this question.

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