From BlenderWiki

Jump to: navigation, search

Grease Pencil: API Changes

Introduction

As part of the GP revamp, some properties have been removed and some added from python API.

The changes in the API are related to the properties that were stored in the layer or stroke and now have been moved out.

Properties at layer level

Theses options have been moved to GPDstroke, because the layer can use several colors.

  • Layer color: RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
  • Layer Fill color: RNA_def_property(srna, "fill_color", PROP_FLOAT, PROP_COLOR_GAMMA);
  • Layer Fill alpha: RNA_def_property(srna, "fill_alpha", PROP_FLOAT, PROP_NONE);

At layer level, the following properties have been added:

  • Blend color: RNA_def_property(srna, "tint_color", PROP_FLOAT, PROP_COLOR_GAMMA);
  • Blend factor: RNA_def_property(srna, "tint_factor", PROP_FLOAT, PROP_NONE);


The line thickness is not used anymore to determine the thickness of the stroke. Now this information has been moved to GPDstroke and the line thickness field has been used to create a line thickness modifier value.

As result of the removal, the line_width parameter now is named layer_change.

The modifier value add or sub the value to the corresponding stroke value. For example, if the stroke thickness is 2 and the modifier value is 1, the line will be drawn with a thickness of 3. There is a new operator to apply the modifier and replace the stroke thickness with new value and set the modifier equal to 0.

Alpha value has ben renamed to Opacity, but internally uses the same field. This value defines a alpha factor for all strokes of the layer. A value of 1 means full opacity.

Properties at stroke level

These properties were added as part of the last smooth patch, but now have been moved to the GPDbrush type.

  • Smoothing factor for new strokes: RNA_def_property(srna, "pen_smooth_factor", PROP_FLOAT, PROP_NONE);
  • Iterations of the Smoothing factor: RNA_def_property(srna, "pen_smooth_steps", PROP_INT, PROP_NONE);
  • Subdivision level for new strokes: RNA_def_property(srna, "pen_subdivision_steps", PROP_INT, PROP_NONE);

The next property has beeen moved to GPDpalettecolor. This property was available only in GPv2 branch.

  • Use High Quality Fill: RNA_def_property(srna, "use_hq_fill", PROP_BOOLEAN, PROP_NONE);

In order to implement the color by stroke, a new property for color name was added to the stroke. This value must be the color name, not a pointer to the color object.

Internally, the code looks for a matching color in the current palette. If the color exists, a pointer is created in a temporary area to speed up drawing. If the palette changes, all colors are remaped to the new colors.

If the new palette does not contain a color with the same name, and there are strokes using the color. A dummy color with the same name is created in the current palette, in order to keep a consistent information of the stroke.

A read-only property allows python code read the triangulated information for High Quality (HQ) fill. This information can be very useful if we need to replicate the same filling process in python.

Properties at point level

The main change at point level is the creation of a new property for the color strength.

This strength property must be a value between 0.0 and 1.0, and controls the alpha factor of the color. This value can be modified using the new strength sculpt brush.

How to adapt add-ons

All the changes done in GP revamp try to reduce the impact in the current add-ons, so only minor changes must be done in order to adapt them.

As the main structure for Layers->Frames->Strokes->Points remains equal, no changes are required at this level. Only if the layer color or fill is used, the add-on must be fixed in order to use the new palette color assigned to the strokes.

If the add-on adds GP information, it will be necessary to implement the creation of one GPDPalette with a GPDPalettecolor. Any stroke needs at least these objects. The corresponding python API is available in order to create them.

# ========================================
# Grease Pencil support
# ========================================
import bpy
from mathutils import Vector
 
def get_gp(scene, gname='gp'):
    gp = scene.grease_pencil
    if not gp:
        gp = bpy.data.grease_pencil.get(gname, None)
        if not gp:
            gp = bpy.data.grease_pencil.new(gname)
            print("Created new Grease Pencil", gp.name)
        scene.grease_pencil = gp
        print("Added Grease Pencil %s to current scene" % (gp.name) ) 
    return gp
 
def get_gp_palette(scene, gname='gp', pname='gp'):
    gp = get_gp(scene, gname)
    palette = gp.palettes.get(pname)
    if not palette:
        palette = gp.palettes.new(pname, set_active=True)
        print("Added new Grease Pencil palette", palette.name)
    return palette
 
def get_gp_color(palette, default_color=(1,1,1) ):
    if len(palette.colors) > 0:
        color = palette.colors[0]
    else:
        color = palette.colors.new()
        color.color=default_color
        print("Added new Grease Pencil color", color.name)
    return color    
 
def get_gp_layer(scene, gname='gp', lname='gp'):
    gp = get_gp(scene, gname)
    if lname in gp.layers:
        layer = gp.layers[lname]
    else:
        layer = gp.layers.new(lname, set_active=True)
        print("Added new Grease Pencil layer", layer.info)
    return layer
 
def get_gp_frame(scene, gname='gp', lname='gp'):
    layer = get_gp_layer(scene, gname, lname)
    if len(layer.frames) == 0:
        frame = layer.frames.new(scene.frame_current)
    else:
        frame = layer.frames[0]
    return frame
 
def get_gp_stroke(scene, gname='gp', lname='gp', pname='gp', default_color=(1,1,1)):
 
    # Create Stroke using the first color in palette
    # Please also see the hint in the text below
 
    palette = get_gp_palette(scene, gname=gname, pname=pname)
    color   = get_gp_color(palette, default_color)
    frame   = get_gp_frame(scene, gname, lname)
 
    #New: You now can add the stroke color when creating a stroke:
    stroke  = frame.strokes.new(colorname=color.name)
 
    stroke.draw_mode = '3DSPACE'
    return stroke
 
def gp_draw_line(scene, fromVector, toVector, gname='gp', lname='gp', pname='gp', default_color=(1,1,1)):
    stroke = get_gp_stroke(scene, gname, lname, pname, default_color)
    stroke.points.add(2)
    stroke.points.foreach_set("co",       fromVector.to_tuple() + toVector.to_tuple())
    stroke.points.foreach_set("select",   (True, True) )
    stroke.points.foreach_set("pressure", (1, 1) )
    stroke.points.foreach_set("strength", (1, 1) )
 
def gp_draw_line_alternative(scene, fromVector, toVector, gname='gp', lname='gp', pname='gp', default_color=(1,1,1)):
    stroke = get_gp_stroke(scene, gname, lname, pname, default_color)
    stroke.points.add(2)
 
    #first point
    stroke.points[0].co       = fromVector.to_tuple()
    stroke.points[0].select   = True
    stroke.points[0].pressure = 1
    stroke.points[0].strength = 1
 
    #second point
    stroke.points[1].co       = toVector.to_tuple()
    stroke.points[1].select   = True
    stroke.points[1].pressure = 1
    stroke.points[1].strength = 1
 
scene=bpy.context.scene
gp_draw_line(scene, Vector((0,0,0)), Vector((2,2,2)))
Blender3D FreeTip.gif
About Stroke colors
Strokes can be created without passing color name. The color can be assigned later (manually in the user interface or by script). However, a stroke without color is invisible, so be sure to eventually assign a color value.