Wednesday, October 7, 2015

GPencil - Using bpy to generate strokes programatically

In response to a question on BlenderArtists this morning, I spent a few minutes poking around with the Python API to check whether it is possible to generate GPencil strokes using a script.


Example output from my test script - It just generates a set of 5 lines in 3D space as a demo of how to use this api

For the benefit of everyone, I've included the test/demo script I wrote at the end of this post. You should be able to just copy and paste it into a text editor (fingers crossed it doesn't grab any of the HTML crap in the process) and start playing around.

Use cases for being able to create Grease Pencil strokes using Python include loading in stroke data from other apps, or for providing addon developers additional ways of adding in-viewport annotations without having to hack around with bgl and draw handlers.




# Demo script to add some gpencil points manually
# NOTE: For the context stuff to work, this should be run from an editor that can have GP data

import bpy


def main(context):
    # add points to new layer
    bpy.ops.gpencil.layer_add()


    gpl = context.active_gpencil_layer
    gpl.info = "Python-Generated Demo Data"
   
    # create new frame to host the strokes
    gpf = gpl.frames.new(context.scene.frame_current)
   
    # create some strokes
    for x in range(5):
        # create new stroke
        stroke = gpf.strokes.new()
        stroke.draw_mode = '3DSPACE'
       
        # create the list of points - all set to defaults
        stroke.points.add(count=x)
       
        # set the stroke point coordinates
        for y, pt in enumerate(stroke.points):
            pt.co = [x, y+1, x*y]
            pt.pressure = 1.0 
       

class GPencilAddDataDemo(bpy.types.Operator):
    """Demo operator for adding grease pencil data"""
    bl_idname = "gpencil.add_data_demo"
    bl_label = "GPencil API Demo"

    @classmethod
    def poll(cls, context):
        return context.area and context.area.type == 'VIEW_3D'

    def execute(self, context):
        main(context)
        return {'FINISHED'}


def register():
    bpy.utils.register_class(GPencilAddDataDemo)


def unregister():
    bpy.utils.unregister_class(GPencilAddDataDemo)


if __name__ == "__main__":
    register()

    # test call
    #bpy.ops.gpencil.add_data_demo()

2 comments:

  1. Hello,

    I am just trying to run your script in Blender 2.76b. I just open blender, go into scripting mode, open the script with the text editor and... nothing happens. Have I missed something?

    ReplyDelete
    Replies
    1. You need to then manually call the operator using the spacebar search, as this script registers an operator (i.e. a "tool") in Blender that can be used in the standard ways.

      Delete