Creating a Blender 2.6 Python add-on

Copyright and example code availability

The text and illustrations in this article are © 2012 Michel Anders, all rights reserved.

The code and example .blend files accompanying this article is distributed under a GPL license; see the code itself for details. It may be downloaded from GitHub

Prerequisites and audience

The examples given in this article were developed with Blender 2.64, the latest version of Blender at the time of writing. Because some of the later examples use new functionality introduced in Blender 2.64 (the Skin Modifier) it strongly recommend downloading and installing the latest version from if you have not already done so.

The goal of this article is to give you a fairly thorough understanding how Python add-ons in Blender work and provide you with enough practical examples to develop actual add-ons. As such you should be quite familiar with Blender and its user interface and some experience with Python is necessary but you absolutely don't have to be an expert programmer to follow the examples and expand upon them. It is sufficient if you understand the basics of object oriented programming.

Table of contents


Python in Blender is an important tool to enhance and extend Blenders already vast functionality. Python is bundled with Blender so there is no need to install it separately and indeed it is an integral part of Blender: Blenders user interface itself is implemented mostly in Python.

Because the user interface itself is written in Python and is designed to be extended and because virtually all internal data structures are accessible through a well documented interface it is pretty straight forward to implement add-ons that are written in Python. This is illustrated by the many add-ons that come bundled with Blender and by the many add-ons people publish online.

Much of what a user can do in Blender is centered on the concept of an operator. And operator essentially represents a basic unit of work, like scaling an object, subdividing a selected edge or calculating a UV-map for example. An operator is often (but not always) invoked through a menu entry or a hotkey and if it has additional properties like size or color, it provides user interface components to alter these properties in an area in the toolbar (on the left of the 3D window, made visible with pressing T )

There are other areas where Python plays an important role and which may be extended by the user, for example defining themes and driving animated properties but in this article we will focus on implementing operators that act on objects and meshes and typically are part of a menu in the 3D-window.

What you will learn

Besides gaining understanding of the way Blenders user interface works, you will learn

  • how to write an operator that is fully integrated with Blender native user interface,
  • how to layout a collection of properties in the toolbar,
  • how to add your operator to a menu,
  • how to install your operator so it will be available from the user preferences,
  • how to manipulate Blender objects, including
  • how to create mesh objects from scratch,
  • how to add modifiers,
  • how to add uv-maps,
  • how to parent objects to another object.

In the next section we see what an operator really is and will implement our first operator.

Anatomy of an operator

Basically a new operator add-on for Blender consists of the following parts:

  • properties, that is all sorts of numbers, vectors, strings and colors that determine the behavior of the add-on
  • a user interface where the user can manipulate the properties
  • code to determine if it is sensible to show the add-on
  • code to do the actual work
  • a few lines of code to insert the add-on in an existing menu and to register an operator

The Blender developers designed the Operator base class in a very clever way: almost anything you need is already provided by the either the Operator base class or the various Property classes, including most functionality to draw a user interface. In many situations you will only have to provide an execute() function and define properties (if applicable).

Example: The basic operator

About the simplest operator that you can imagine is one that moves the active object one Blender unit along the x-axis. The code shown below does just that.

code:, part of addon-move.blend

import bpy

class MoveOperator(bpy.types.Operator):
    bl_idname = "object.move_operator"
    bl_label = "Move Operator"

    def execute(self, context):
        context.active_object.location.x += 1.0
        return {'FINISHED'}

def register():

if __name__ == "__main__":

You can simply type this into the text editor and click the run script button

If there were no syntax errors the operator is now available to the user. Make sure you have an active object to test the new add-on. In the 3D-window you may now press the space-bar and type 'Move O' in the search box. Probably the only selection left in the list of choices is now our new operator. Click it to execute it and see how your active object is translated along the x-axis. Hurray!

Tip: The Blender console

If there was a syntax error or if something else went wrong during the execution of the operator a message is shown briefly in Blenders information bar at the top of the screen and additional information is listed in the console.

This console is not shown by default but in the Windows version of Blender this can be toggled from the main menu: Window->Toggle System Console. For other operating systems it is necessary to start Blender from a command line terminal instead of clicking an icon. Any messages will now be shown inside this terminal.

The Basic Operator: Example Breakdown

Our new operator is defined as a class MoveOperator that is derived from Blenders Operator class. The first lines define two class variables: bl_idname, which provides an internal name for our operator and bl_label, which provides a descriptive name that is used in for example menus. The names of the class variables start with bl_ to identify them as Blender specific and to distinguish them from any class variables you may define for your own purposes. We will encounter some additional Blender variables later on. Note that the bl_idname we have chosen starts with 'object'. This is a convention that identifies this operator as acting on a Blender object instead of for instance on a mesh or a texture.

The next thing we encounter is the definition of the function execute(). This function is the one that is called when the user invokes the operator. It is passed a context argument which holds information on the context the operator was invoked in. The context effectively records the state of Blender, for example which is the active object or whether we are in object mode or in edit mode. Our execute function refers to the active object in the context and adds one to the x component of its location.

To signal that it is done, the execute() function returns a set with a single string 'FINISHED'. This somewhat peculiar behavior is Blender specific and we will encounter other examples later on.

At this point we have a class but we still have to inform Blender to make it available to the user. That is what the definition of the register() function is for. The final lines make sure that if we click the Run Script button in the text editor we indeed register the operator. We could have called the register_class() function directly but by providing it at the file level we provide a means to register our operator class automatically when we install our script as an add-on (see the section Example: Distribution of an add-on)

Tip: using an external editor

Before we start adding properties it is a good idea to set up the way we develop our add-on in a slightly different way. An operator with properties will appear in the toolbar on the left of the 3d window once it is invoked and there we can change the properties and undo them if we are not satisfied with the results. This is nice but undoing something will also undo changes in the text editor if they were made after the invocation. This may sound confusing and it is because it can lead to unexpected annoyances when text you typed in the text editor is reverted without you wanting it. Therefore it is a good idea to edit your add-on in an external editor and run it during development from the text editor with the few lines shown below.

You might run it directly from any directory (for example the add-on installation directory we will encounter later on) or from the same directory as where your .blend file is stored. The code below does the latter: it runs the script '' from the same directory as the .blend file.

Code:, part of add-move3.blend

import bpy
import os

filename = os.path.join(os.path.dirname(, "")
exec(compile(open(filename).read(), filename, 'exec'))

Example: Add an operator to a menu

Invoking an operator from the space-bar menu is fine, but it is far more convenient to add the operator a meaningful menu. Our move operator acts on an object in the 3D View window so it would be logical to add our operator to the object menu in the 3d View.

All these menus are available from within scripts and Blender offers a convenient way to determine what a menu is called. If you let the mouse cursor hover above a menu the name of the menu is shown in the tooltip:

In this case we see that the object menu in the 3D View is called 'VIEW3D_MT_object', something we encounter again when we analyze the code for our new add-on. But let us first run the script (part of addon-move2.blend).

When we run the script we can now invoke our operator from the object menu to let the active object move as shown below:

Code:, part of addon-move2.blend

import bpy

class Move2Operator(bpy.types.Operator):
    """Move2 Operator"""
    bl_idname = "object.move2_operator"
    bl_label = "Move2 Operator"

    def execute(self, context):
        context.active_object.location.x += 1.0
        return {'FINISHED'}

def add_object_button(self, context):

def register():
if __name__ == "__main__":

Add an operator to a menu: Example Breakdown

In order to make our operator part of a menu we have to append it. Here this is done in the register() function. The add_object_button argument is a function that takes a self argument that refers to the menu being displayed on screen and a context argument. It adds the operator to the menu layout (more on layouts in the section on properties) by calling the operator() function of that layout. The three arguments passed are the internal name of our operator, the text that should appear in the menu and the icon to use.

The docstring of the operator will appear as the hover text when you leave your mouse over the menu entry and we use this same sting here to determine the actual text of the entry but there is no reason why these should be the same, in fact normally the hover text would be a bit more instructional.

Example: Add properties to an operator

Many operators change their behavior based on properties set by the user. We would like our operator to move in a direction and amount that we specify. We therefore define two properties, distance and direction, and let our execute() function use those values to effect its move.

Blender's module contains a number of useful attributes and her we use filepath to get the full filename of the .blend file we are using. We use Python's platform neutral filename manipulation functions get at the directory part and append the name of the script we want to run. This script is then compiled and executed.

Now let's have a look how we can augment our operator with distance and direction properties that might be manipulated by the user. The idea is that once selected from the 3D View object menu the operator's properties will appear in the toolbar on the left side of the 2d View as shown below:


import bpy
from bpy.types import Operator
from bpy.props import FloatVectorProperty, FloatProperty

class Move3Operator(bpy.types.Operator):
 """Move3 Operator"""
 bl_idname = "object.move3_operator"
 bl_label = "Move3 Operator"
 bl_options = {'REGISTER', 'UNDO'}

 direction = FloatVectorProperty(
   default=(1.0, 1.0, 1.0),
   description="move direction"
 distance = FloatProperty(

 def execute(self, context):
  dir = self.direction.normalized()
  context.active_object.location += self.distance * dir
  return {'FINISHED'}
 def poll(cls, context):
  ob = context.active_object
  return ob is not None and ob.mode == 'OBJECT'

def add_object_button(self, context):

def register():

if __name__ == "__main__":

Add properties to an operator: Example Breakdown

Registering an operator is not sufficient to make it appear in the toolbar area when it is selected from a menu. For that we need to set bl_options to a set containing the string 'REGISTER'. We also add 'UNDO' to provide the user with a rest button for this operator.

Our properties are defined as class variables that are initialized using appropriate property factory functions. Blender had a whole host of these, documented in the API documentation of the bpy.props module. We define direction as a FloatVectorProperty, that is a vector with x y an z components and although the FloatVectorProperty offers a subtype 'DISTANCE' that displays a sphere like widget that is intuitive for things like surface normals, we stick with the 'XYZ' here.

We define distance as a FloatProperty. A FloatProperty can have (among other things) a name, a default value and minimum and maximum values. It also takes subtype and unit arguments which won't change the value itself but will alter the display of the widget and add appropriate units, if this is selected in the units tab of scene properties (see image below)

Our new execute() function retrieves the distance and the direction and after normalizing the direction changes the active object's location.

If we now click Run Script and invoke our operator form Object -> Move3 Operator the toolbar in the 3D window now displays our properties without us having anything to code to achieve this. Pretty neat, isn't it?

You may have noted that the Operator class takes care of displaying the properties we have defined. It is possible to determine the layout ourselves by providing a draw() function and that is what we'll do in the final example but for simple operators this is hardly ever necessary.

The final thing to take into account is the poll() function. This class method provides us with a way to control whether the operator is applicable. Here we have defined it to check if there is an active object at all and if so if it is in object mode. If not we return False. If an operator provides a poll() function and it returns False, any menu entry for this operator will be grayed out.

Example: Distribution of an add-on

Up until now we have run our script from the text editor but normally we would want the script to be available for all .blend files and the user should have the choice to enable the add-on from the user preferences.

To provide Blender and the user with relevant information about our add-on we add some extra information at the beginning of our code as shown below:

Code: (part)

bl_info = {
 "name": "Move4 Object",
 "author": "Michel Anders (varkenvarken)",
 "version": (1, 0),
 "blender": (2, 6, 4),
 "location": "View3D > Object > Move4 Object",
 "description": "Moves the active Object",
 "warning": "",
 "wiki_url": "",
 "tracker_url": "",
 "category": "Object"}

If we now save our script to the add-ons directory and restart Blender, the add-on can be enabled from File->User Preferences by ticking the check box:

Because we defined the category to be 'Object' it shows up in the Object section of the add-ons.

In the next section we step up the tempo and we will create an add-on that does not simple modify some attributes of an existing object but creates a completely new configurable object.

Example: Generating trees: the L-system add-on

Add-ons can do a lot more than just move the active object about and in fact Blender comes bundled with a set of most spectacular add-ons which are 'just' operators. Clever add-ons like for example the Bolt Factory, Masonry wall and Sapling nicely show what might be achieved.

With these fine examples as our motivation, let's try our hand at an add-on that will create all sorts of tree and plant-like objects based on L-systems.


L-systems are basically a set of string rewriting rules, but the interesting part is that we can interpret these strings as instructions to draw branches and leaves. Varying those rules or changing the number of iterations can provide us quickly with a whole host of different tree structures. If the rules (or 'productions') are chosen well, the results mimic the structures of real world plants or trees (you can read more on this on or go in depth by reading the freely available book )

In this final section we will develop an add-on that

  • let's us specify the rules for an l-system
  • creates a mesh object that represent the resulting tree
  • adds skin and subdivision modifiers to this mesh to create solid looking branches
  • adds UV-mapped leaves parented to this mesh and
  • lets the user save interesting results as operator presets.

Even though there is a lot more functionality than in our move operator the l-system operator has the same general outline:

  • the add-on provides information about itself in the bl_info dictionary
  • properties are defined as class attributes of the operator
  • the actual work of creating a new object is done in the execute() method
  • module level register() and unregister() functions are provided to register the operator and to create a menu entry

Of course interpreting a string a series of instructions to create a mesh is somewhat more involved than just moving an object so the execute() method is significantly larger than the previous versions we encountered. The same goes for properties, although the properties used here are by no means more difficult, there are quite a lot more that we want to arrange in an orderly fashion.

Using the l-system add-on

Before we look at the code in detail let's see how we can actually use the add-on. The add-on consists of more than one Python source file so it is distributed as a package: a directory called addon-lsystem that contains two files and The first contains the code of the operator the latter the code to interpret the strings.

To use the add-on:

  • Install the addon-lsystem directory and its containing files in the scripts\addons directory
  • Restart Blender and enable the add-on (it is in the Add Mesh section)

  • Invoke the operator from the File -> Add -> Mesh -> New Lsystem Object

  • The (initially mostly empty) properties will show up in the toolbar. If the toolbar isn't present in the 3d View you should press T

  • Change the properties anyway you want. For example by changing the number of productions to 2 and entering those productions, the start string, the iterations and the angle as shown

You will get the famous dragon curve (

When interpreting the result of the iterated productions the characters in the result string map to the following actions:

+, -

rotate around the right axis

/, \

rotate around the up axis (yaw)

<, >

rotate around the forward axis (roll)

the amount of rotation is set by the angle property

[, ]

push or pop state


rotate a random amount

!, @

expand or shrink the size of a forward step ( a branch segment or leaf)

#, %

fatten or slink the radius of a branch


produce an edge (a branch segment)


produce an instance of a uv-mapped square ( a leaf )

Characters not in the list are simply ignored.

The object(s) produced can be influenced by the properties in the interpretation section:


the number of times the productions should be applied


the random seed to be used (affects the & operator)


the angle used for rotations


the direction of the drift added to F operators (used to simulate for example gravity)

tropism size

the size of the additional drift

Properties and layout

To manipulate an l-system we need to provide the user with quite a number of options. Our first task is to provide a layout that orders these properties in a logical way. This is what it will look like:

The layout of most options is straightforward and in previous examples we did not bother to provide a draw() function for our operator. But here we have quite a number of options so it makes sense to separate these visually. And there is another special issue here: the rewriting rules are presented as StringProperty attributes but we want to give the user the option to increase or decrease the number of rewriting rules. In the code below we will see how we can add a property dynamically to an operator class.

code snippet: properties, from addon-lsystem/

class OBJECT_OT_add_lsystem(Operator):
 """Add an L-system Object"""
 bl_idname  = "mesh.add_lsystem"
 bl_label  = "Add Lsystem Object"
 bl_description = "Create a new Lsystem Object"
 bl_options  = {'REGISTER', 'UNDO', 'PRESET'}

 nproductions = IntProperty(
  name = "productions",
  min = 0,
  max = 50,
  update = nupdate )
 niterations = IntProperty(
  name = "iterations",
  min = 0,
  max = 20 )
 seed = IntProperty(name="seed")
 start = StringProperty(name='start')
 angle = FloatProperty(
  name  = 'angle',
  default  = radians(30),
  subtype = 'ANGLE',
  description = "size in degrees of angle operators" )
 tropism = FloatVectorProperty(
  name  = 'tropism',
  subtype = 'DIRECTION',
  description = "direction of tropism" )
 tropismsize = FloatProperty(
  name  = 'tropism size',
  description ="size of tropism" )

Properties and layout: Example breakdown

The class starts out by defining a number of properties:

  • nproductions, an IntProperty that allows us to set the number of rewriting rules. The rewriting rules themselves are pairs of StringProperty attributes that get added as needed by the nupdate() function that we will see later on. The nupdate() function is passed as the value of de update parameter of this InTProperty and will be called each time the nproduction property is changed and on its initialization,
  • niterations, an IntProperty that specifies how many time we should apply the rewriting rules to the given start string,
  • seed, an IntProperty used a a random seed for the & operator in rewrite rules
  • start, a StringProperty that specified the initial string to apply the rewriting rules to
  • angle, a FloatProperty specifying the angle in degrees of the > < + - \ and / operators in rewrite rules,
  • tropism, a FloatVectorProperty indicating the direction of the drift applied to the F module in rewriting rules, for example to simulate the effect of gravity or light directed growth,
  • tropismsize, a FloatProperty with the amount or weight of the tropism.

The nupdate() function is called each time the value of the nproductions property changes and is implemented as a function at the module level:

code snippet: the nupdate() function, from addon-lsystem/

def nupdate(self,context):

 for n in range(self.nproductions):
  namep = 'prod' + str(n+1)
  namem = 'mod' + str(n+1)

  except AttributeError:
   setattr(self.__class__, namep,
     name = namep,
     description = "replacement string")
  except AttributeError:
   setattr(self.__class__, namem,
     name = str(n+1),
     description = "a single character module",

For as many productions as needed it checks whether the prod<n> and mod<n> attributes are present and if not it catches the AttributeError exception and adds the appropriate StringProperty. Note that we never remove these attributes but the draw() method shown below simply doesn't display them:

code snippet: the draw() function, from addon-lsystem/

def draw(self, context):
  layout = self.layout
  box =
  box.prop(self, 'nproductions')
  box =
  if getattr(self,'start')=='':
  box.prop(self, 'start')

  for i in range(self.nproductions):
   namep = 'prod' + str(i+1)
   namem = 'mod' + str(i+1)
   box =
   row = box.row(align=True)
   if getattr(self,namem) == '' or \
    getattr(self,namem) == '':
  box =
  box.label(text="Interpretation section")

As we saw earlier we present all these properties visually arranged in boxes. The nproductions property is presented in a box of its own. The start string has its own box as well but the alert attribute of this box is set when the start property is empty. This will render the box with a red background if we forget to supply a start string for out l-system.

Next we draw a box for each production present. A production consists of a left hand side (the single letter 'module name' as it is called in most l-systems) and a right hand side, a possibly multi character string. To align these two side by side we add a row layout to the box and set the alert attribute of this row if either of these properties is empty. The right hand property is added with its text attribute set to the empty string to suppress using its name as a label. This way the left and right hand side will be really flush together as shown in the image below:

The rest the properties is all about the interpretation of the result string and rendering it as a Blender object so these are grouped in a single box with a descriptive label at the top.

Tip: Presets

By adding the option 'PRESET' to the bl_options attribute of an operator is becomes possible for the user to save a set of property values she likes as a preset:

bl_options = {'REGISTER', 'UNDO', 'PRESET'}

Presets are saved in the user's profile, on Windows for example in:

C:\Users\Michel\AppData\Roaming\Blender Foundation\Blender\2.64\scripts\presets\operator

For each operator's presets a subdirectory is created and each preset is saved as a small Python scripts. It is possible to distribute these presets, other users can simple copy the directory plus Python files to their own profile or the scripts\presets\operator directory inside Blender's installation directory.

The lsystem class

Now that we have the rewriting rules and other properties available we can implement the execute() function that will iterate the l-system and create an object based on the end result. A complete description of the class is out of scope of this article but let's have a quick look at how execute() utilizes this class.

code snippet: the execute() function, from addon-lsystem/

def iterate(self):
  for i in range(self.nproductions):
   namep = 'prod' + str(i+1)
   namem = 'mod' + str(i+1)
   prod[getattr(self,namem)] = getattr(self,namep)
  for i in range(self.niterations):
   s = "".join(prod[c] if c in prod else c for c in s)
  return s
 def execute(self, context):

  <<< code ommited >>>

The execute() function first calls the interpret() method which takes the contents of the start property and applies the rewrite rules the required number of times before returning the end result as a single string.

code snippet: the interpret() function, from addon-lsystem/

def interpret(self, s, context):
  q = None
  qv = ((0.5,0,0),(0.5,1,0),(-0.5,1,0),(-0.5,0,0))
  verts = []
  edges = []
  quads = []
  self.radii = []
  t = Turtle( self.tropism,
     self.seed )
  for e in t.interpret(s):
   if isinstance(e,Edge):
    if e.start in verts:
     si = verts.index(e.start)
    if e.end in verts:
     ei = verts.index(e.end)
    <<< code ommited >>>
  mesh ='lsystem')
  mesh.from_pydata(verts, edges, [])
  obj,base = self.add_obj(mesh, context)
  for ob in context.scene.objects: = False = True = obj
  <<< code parenting Quad to the main object ommited >>>
  return base

The interpret() method will return a Blender mesh object based on a Turtle interpretation of the string passed to it as an argument. This mesh object will consist of vertices and edges only but the object will be rendered solid later on by adding a skin modifier.

The Turtle object (the class is defined in the lsystem module not shown here) may be iterated over to return different kind of named tuples. For any F character in the string it is interpreting it will return a named tuple of the class Edge. Its start and end attributes hold vertices. If either of these vertices is not yet present in the verts list we add it. In both cases we retain the indices into this list to construct an edge (a tuple of indices) that we append to the edge array. (We also save the radius attribute that will later be used to control the local thickness of the skin modifier. This radius is increased and decreased by the # and % operators respectively in the string that is being interpreted.)

When all the characters in the string are interpreted we proceed by creating a new mesh called lsystem (of course in Blender it may end up with a numerical suffix if a mesh with that name is already present) and call its from_pydata() method to construct the mesh from our lists of vertices and edges.

A mesh is not yet a Blender object linked to a scene and to that end we call the add_obj() method which returns both the Blender object and the base object (a base object links an object to a scene, allowing the same object to be used in more than one scene. add-obj() adds the object it constructs to the current scene). The final steps are to deselect all objects in the current scene and select our newly added object and to indicate in the context that the new object is the active one.

The add_obj() method is pretty straight forward:

code snippet: the add_obj() function, from addon-lsystem/

 def add_obj(obdata, context):
  scene = context.scene
  obj_new =, obdata)
  base =
  return obj_new,base

It retrieves the current scene from the context and then creates a new Blender object. The new Blender object is given the same name as the mesh data it contains. Next we link the new object to the current scene and return both the object and the base object.

Creating a tree like mesh with a skin modifier

The interpreter part of the lsystem provides us with a tuple of start and end points for each F character in the end result. We want to create a mesh object with vertices and connecting edges based on these end points and add a skin modifier to this mesh object to add some volume:

code snippet: the execute() function, from addon-lsystem/

def execute(self, context):
  skinverts = \[0].data
  for i,v in enumerate(skinverts):
   v.radius = [self.radii[i],self.radii[i]]
  context.active_object.modifiers[1].levels = 2

  return {'FINISHED'}

We use the modifier_add() operator to add a skin modifier to the active object which is our newly created object. Because this is the first modifier we add we can access it with index 0 in the modifiers attribute and set its use_smooth_shade attribute to True. This necessary because an object with a skin modifier doesn't heed the regular smooth shading attribute normally used for an object.

The skin modifier also added a so called vertex layer, skin_vertices, that we iterate over to replace the default radii with the radii we calculated using # or % operators.

We finish by adding a second modifier, a subsurface modifier with two levels of subdivisions, making everything look really smooth.

Adding leaves with UV-maps

When the lsystem interpreter encounters a Q character in the end result, it hands us the current position and orientation vectors (up, right, forward) as a namedtuple of type Quad. We use this to position and orient a mesh object consisting of a single quad face. We do not want to replicate this geometry for possibly thousands of objects so we let the objects that we instantiate point to the same mesh.

The omitted code in the execute() method that deals with Quads looks like this:

code snippet: execute() part 2

elif isinstance(e, Quad):
    if q is None:
     q ='lsystem-leaf')
     q.from_pydata(qv, [], [(0,1,2,3)])
    obj,base = self.add_obj(q, context)
    for i in (0,1,2):
     r[i][0] = e.right[i]
     r[i][1] = e.up[i]
     r[i][2] = e.forward[i]
    obj.matrix_world = Matrix.Translation(e.pos)*r

We only want to create the mesh data once so our first check is to see if we already did so.

We also add a uv-layer to the single mesh. This way, if we add a material with a uv mapped texture to the mesh, all objects are equipped with a fitting image in one go. Note that we not actually set any uv coordinates in this new uv-layer, we simply use the default coordinates that are created when the new layer is added. This will ensure that a uv-mapped texture will perfectly fit our square.

Then we add a new object to the scene that refers to the mesh data. So we end up with an object for every leaf but just one mesh.

We orient this object by creating a Matrix instance that represents the orientation in the world and set the object's matrix_world attribute to the product of that rotation and a translation to the current position.

We end by appending a reference to this object the quads list.

Parenting objects

The end result of the l-system operator might not be a single mesh object but a whole bunch of objects if our productions generate a number of leaves as well. In such a situation it might be a good idea to parent the leaves to the main mesh object to make the life of the user a little easier when she wants to move the tree and the leaves. That was the purpose of the quads list that holds references to all the leaves. In the final part of the execute() method we omitted earlier we iterate over this list and set the parent attribute of each object to the main object:

code snippet: execute() part 3

mesh ='lsystem')
  mesh.from_pydata(verts, edges, [])
  obj,base = self.add_obj(mesh, context)
  for ob in context.scene.objects: = False = True = obj
  for q in quads:
  return base


This section provides you with some exercises so you can test yourself if you grasp the concept of operator completely. Don't be alarmed if you don't get it to work in one go, each exercise comes example code that is part of the code distribution.

Exercise 1: Making the skin modifier optional

When the result of our lsystem consists of many edges and leaves the interaction might feel sluggish on less powerful PCs so it might be a good idea to add a checkbox to make this optional so that you can manipulate the mesh until you are are satisfied and only mark a checkbox when you're done.

A checkbox may be implemented by adding a BoolProperty attribute and changing the part of the execute() method that deals with adding modifiers to act on the contents of this attribute. It should look something like:

Hint: when you add a property to an operator that provides a draw() method you should not forget to add the new property to your layout otherwise it will not be visible. Full code that implements this functionality can be found in the Examples\Example 1 directory of the code distribution.

Exercise 2: Adding arbitrary objects instead of just leaves

The main object of our lsystem is formed by skinning edges of a mesh and we have the possibility of adding leaves in the form of simple square meshes but in some scenarios this might not be enough. For example, we might want to add fruits or blooms or create structures that have nothing to do with trees.

A useful addition therefore might be to enhance the l-system add-on with the possibility to add arbitrary Blender objects. The idea is that productions might contain references to any existing object like {Cube}, for example as shown on the left:

This example will produce an object like the one shown on the right.

Hint: the module already will return a namedtuple of type BObject if it encounters a string like {Cube}. Besides pos, up, right and forward attributes like the Quad type, it also has a name attribute. Your challenge is to enhance the interpret() method of the lsystem operator to recognize that a BObject is being returned and act accordingly by creating a new object with a duplicate of the original's object data.

Full code that implements this functionality can be found in the Examples\Example 2 directory of the code distribution.

References and further reading

When developing add-ons in Blender you cannot do without the API documentation that you can find on Not only will you find information on bundled scripts which can be a source of education on its own but there is also a full reference to the API at (note that this link will redirect you to the latest version of the API docs despite its name).It also provides several links with tips and tricks and an overview of the API.

Another excellent source of examples is hidden under the Templates button in the Text Editor menu. Clicking on any of the options listed there will create a new text with sample code. Many examples are provided here, not only for operators but also code for all kinds of other situations where Python is used in Blender.


  1. Wow great work! Have not read everything yet, but seems like a very comprehensive and complete tutorial. I'll be sure to follow it as son as I have some free time. I am trying to learn blender scripting and python coding in general.

    Many thanks, this will come in handy

    BTW: I believe you made some small markup mistake with your last image in the article, it seems wrongly formatted

    1. Hi Duarte,

      fixed the markup, thanks for your comment!

  2. What version of Python are you using? Can't get even the simple code to work with 3.2.

  3. nice work! is it possible to pack this into a pdf for offline reference?

    1. Yes a pdf is possible, I might post one in the (near) future, but this week I am bit busy so please don't hold your breath :-)

    2. click at top of the page, hold and drag to bottom. Control-c, open up libreoffice-writer, control-v, export to pdf. done :)

    3. its been a while. Any nes of a pdf?

  4. Found the problem:
    in your blog examples, you need:

    an underscore between bl and idname and one between move and operator in the same line

    an underscore between active and object in the execute block

    and two underscores on each side of the word name in the last block.

    1. Hi Ray, I don't get exactly: if I search for idname if find every instance preceeded by an underscore. Did I miss one?

  5. Excellent and very well tutorial. Thank you!

  6. Very nice and useful.
    What i would like you to add is all what you have to do when your plugin is ready : publishing, adding to the addons list, help page and so on...
    Thanks in advance if you think you can do that !

  7. Hi. Very nice addon. I like it much, but it is not as good as l-system used in Houdini. Do you think about develop it more, because it have a potential. I started work to make it a little better by adding same function. For example declare angle in side string. I have same ideas haw make it better.

    Here is link to my version

  8. In, the line...
    dir = self.direction.normalized()
    does not work because a FloatVectorProperty has no such attribute. I have spent a few hours trying to make it work by researching mathutils. I tried including that and since there is no FloatVector.normalize() I tried things like...
    dir = mathutils.Vector(self.direction).normalized()
    but the length of whatever sequence 'self.direction' returns is only 1.

    Don't think I'll get through the rest if I'm stumped so early!

    1. Found it. Strange error to get but I had an extraneous comma after the closing parenthesis of one of the properties. Very strange error!

  9. In the code snippet of the draw function is standing a small mistake. There is standing 2 times namem instead of namem and namep. In the complete source code from the zip file you provided it is correct.

    if getattr(self,namem) == '' or \
    getattr(self,namem) == '':

  10. what is the the name for the "Add" Menu (Shift + A) ??
    I'd like to append my operator there.

    1. found it:

      INFO_MT_mesh_add for adding op in "Add > Mesh"

      more paths:

  11. I really liked your tutorial.I hope there will be more.

    I'm currently trying to inpruve a blender addon but problem is that i don't really understand how and where textures are stored in pyhon. I tryed to to use the Blender API documentation but is so huge that i got lost in it. Can you give explain me textured are stored ? O give me a shorter documentation where i can get o hold of it.

  12. I've read quite a few of your comments(and learned quite a bit) about scripting in Blender in different forums and it was difficult to figure out how to contact you with a question.

    Any way, I've found a method to get blender to render and composite my scenes about 10 to 20 times faster. I wrote a script so I would not have to manually set it up each time. That went well.

    However with attempting to make an addon, my programming skills fell short.

    What I'm attempting to create is an addon similar to the Properties/Modifier interface that is already available, with the Add, Stack and arrange items in the stack.

    One type of item in the stack would have a dropdown that would allow selection of a certain scene, the other type would allow the selection of a certain node and set it's input image.

    If you or anyone you know of is capable of and has the time to assist with this, please let me know. I will certainly be able to compensate any one for their time.

    Your time and consideration are greatly appreciate.

  13. Very helpful thankyou. Nice l-system example too

  14. Hi there - is there a way to calculate the surface area and volume of the trees?

  15. Hi, I just tried the first example ( with selected cube (standard template after opening blender) and it does nothing at all. I checked blender console, but no error there. I use Blender 2.68a on Windows Vista.

    I was wondering, did somebody else tried it too? Did it work? If not, maybe some line is missing in the example. The register() procedure looks quite short to me. U called only register_class(). Something like class.execute() is missing to me.

  16. Hi everyone,

    I just want to run python scrypt: bpy.ops.render.netclientstart()
    when the blend file is opening (everything is set, need only start service)

    How to create a script to "automatically click" the button "start network rendering service".

    Just that. I couldn't find the answer here.

  17. Is the accompanying code for this article still available? It looks like a great tutorial, but the download link at the top is broken.

  18. @tim tylor: i just checked
    and it is very much alive...

  19. This comment has been removed by a blog administrator.

  20. This comment has been removed by a blog administrator.

  21. This comment has been removed by a blog administrator.

  22. Programming is combination of intelligent and creative work. Programmers can do anything with code. The entire Programming tutorials that you mention here on this blog are awesome. Beginners Heap also provides latest tutorials of Programming from beginning to advance level.
    Be with us to learn programming in new and creative way.

  23. Thanks for sharing the information about the Python and keep updating us.This information is really useful to me.

  24. the article provided by you is very nice and it is very helpful to know about the python ..i found a article related to you..once you can check it out.
    python online training

  25. This comment has been removed by the author.

  26. This comment has been removed by the author.

  27. This Carbonite is a map and quest tracking addon. The map feature will go from your standard map to a more google maps type terrain map. more info

  28. Really appreciated the information and please keep sharing, I would like to share some information regarding online training.Maxmunus Solutions is providing the best quality of this PYTHON programming language. and the training will be online and very convenient for the learner.This course gives you the knowledge you need to achieve success.

    For Joining online training batches please feel free to call or email us.
    Email :
    Contact No.-+91-9066638196/91-9738075708

  29. This is an awesome post. Really very informative and creative contents. This concept is a good way to enhance the knowledge.

    Like it and help me to development very well Thank you for this brief explanation and very nice information. Well got good

    Python Training in Gurgaon

  30. This comment has been removed by the author.

  31. Awesome tutorial! I love how thorough it is! If anyone is looking for more tutorials, check out - domino animation in only 10 lines of code.

  32. This comment has been removed by the author.

  33. Nice blog this information is unique information i haven't seen ever by seeing this blog i came know lots of new things
    python training in Hyderabad the best career

  34. It is amazing and wonderful to visit your site.Thanks for sharing this information,this is useful to me...
    Click here:
    angularjs training in tambaram
    Click here:
    angularjs6 Training in Chennai
    Click here:
    angularjs6 Training in Chennai

  35. I have been meaning to write something like this on my website and you have given me an idea. Cheers.
    Click here:
    Microsoft azure training in chennai
    Click here:
    Microsoft azure training in online

  36. This is a nice article here with some useful tips for those who are not used-to comment that frequently. Thanks for this helpful information I agree with all points you have given to us. I will follow all of them.
    Blueprism training in Chennai

    Blueprism training in Bangalore

    Blueprism training in Pune

    Blueprism online training

    Blueprism training in tambaram

  37. Good Post! Thank you so much for sharing this pretty post, it was so good to read and useful to improve my knowledge as updated one, keep blogging.
    Devops training in velachery
    Devops training in annanagar
    Devops training in sholinganallur

  38. Good Post! you have furnished the right information that will be useful to anyone at all time. Thanks for sharing your Ideas.

    Python Training in Chennai
    Python Training

  39. Nice work! It is really very helpful. Thanks for sharing!!
    Data Science Online Traning

  40. Nice information, this is very helpful.. thanks for sharing!
    Click here for more: DevOps Online Training

  41. I ‘d mention that most of us visitors are endowed to exist in a fabulous place with very many wonderful individuals with very helpful things.
    industrial safety course in chennai

  42. Good Post, I am a big believer in posting comments on sites to let the blog writers know that they ve added something advantageous to the world wide web.
    java training in chennai | java training in bangalore

    java online training | java training in pune

  43. I simply wanted to write down a quick word to say thanks to you for those wonderful tips and hints you are showing on this site.
    offshore safety course in chennai

  44. Good Post, I am a big believer in posting comments on sites to let the blog writers know that they ve added something advantageous to the world wide web.
    Golden gate Training Classes

    Hadoop Training Classes

  45. Good Post, I am a big believer in posting comments on sites to let the blog writers know that they ve added something advantageous to the world wide web.
    Abinitio Training From India

    Microsoft Azure Training From India

  46. Thanks for sharing such an amazing blog,really useful and informative.

    Website Design Course in Bangalore | Web Designing Course in Bangalore

  47. I like your blog, I read this blog please update more content on python, further check it once at python online course

  48. Hmm, it seems like your site ate my first comment (it was extremely long) so I guess I’ll just sum it up what I had written and say, I’m thoroughly enjoying your blog. I as well as an aspiring blog writer, but I’m still new to the whole thing. Do you have any recommendations for newbie blog writers? I’d appreciate it.

    AWS Interview Questions And Answers

    AWS Training in Pune | Best Amazon Web Services Training in Pune

    Amazon Web Services Training in Pune | Best AWS Training in Pune

    AWS Online Training | Online AWS Certification Course - Gangboard

  49. After reading your post I understood that last week was with full of surprises and happiness for you. Congratz! Even though the website is work related, you can update small events in your life and share your happiness with us too.

    angularjs Training in chennai
    angularjs Training in chennai

    angularjs-Training in tambaram

    angularjs-Training in sholinganallur

    angularjs-Training in velachery

  50. nice work keep it up thanks for sharing the knowledge.
    Datastage Online Training

  51. Hey, Wow all the posts are very informative for the people who visit this site. Good work! We also have a Website. Please feel free to visit our site. Thank you for sharing.
    Well written article python. Thank You Sharing with development for beginners | future of android development 2018

  52. This comment has been removed by the author.

  53. Thank you for sharing your article. Great efforts put it to find the list of articles which is very useful to know, Definitely will share the same to other forums.
    Data Science Training in chennai at Credo Systemz | data science course fees in chennai | data science course in chennai quora | data science with python training in chennai

  54. Thanks for such a great article here. I was searching for something like this for quite a long time and at last, I’ve found it on your blog. It was definitely interesting for me to read about their market situation nowadays. Well written article.Thank You for Sharing with Us angular 7 training in chennai | angular 7 training in velachery | Best angular training institute in chennai

  55. Thanks for sharing this valuable information to our vision. You have posted a worthy blog keep sharing.

    Guest posting sites

  56. Very useful post. The information stated in the article is very practical. The writing style is also easily understandable. 361 minds offers MBA programs online. It also provides learning on the gateway of future technology which is called Big Data with a certification.

    big data training in chennai

    hadoop training in chennai

  57. I like your blog, I read this blog please update more content on python, further check it once at python online course

  58. This post is much helpful for us. This is really very massive value to all the readers and it will be the only reason for the post to get popular with great authority.
    German Classes in Chennai
    German Language Classes in Chennai
    German Language Course in Chennai
    Best Java Training Institute in Chennai
    Java Training
    Java Classes in Chennai

  59. Such an informative blog that i have red yet.I hope the data you gave is helpful for the students.i have read it very interesting information's.
    AngularJS Training in Ashok Nagar
    AngularJS Training in Perambur
    Angular JS Training courses near me
    Angularjs Training in Bangalore

  60. Good job in presenting the correct content with the clear explanation. The content looks real with valid information. Good Work

    DevOps is currently a popular model currently organizations all over the world moving towards to it. Your post gave a clear idea about knowing the DevOps model and its importance.

    Good to learn about DevOps at this time.

    devops training in chennai | devops training in chennai with placement | devops training in chennai omr | devops training in velachery | devops training in chennai tambaram | devops institutes in chennai | devops certification in chennai | trending technologies list 2018

  61. Hi , thanks for sharing your information.The insights are really helpful and informative.
    Robotics in Coimbatore
    Learn robotics online

  62. Nice post. By reading your blog, i get inspired and this provides some useful information. Thank you for posting this exclusive post for our vision...Best Python Training Institute In Hyderabad | Best Python Online Training Institute

  63. I always enjoy reading quality articles by an individual who is obviously knowledgeable on their chosen subject. Ill be watching this post with much interest. Keep up the great work, I will be back..Best Python Training Institute In Chennai

  64. Which is the best training institute for PLC, SCADA, and DCS, and where is it located in India?
    LIVEWIRE is in association with 250+ corporates, who grab candidates from our centres when they match their job requirement. We offer all these opening to the students.Get trained through an ISO certified institute. Our course completion certificate and material are globally recognized. If you want to more details contact us: #LivewireVelachery, #PLCTraininginChennai,#PLCTrainingInstituteinChennai,#PLCTraininginVelachery, 9384409662

  65. I have gone through your blog, it was very much useful for me and because of your blog, and also I gained many unknown information, the way you have clearly explained is really fantastic. Kindly post more like this, Thank You.
    Aviation Academy in Chennai
    Aviation Courses in Chennai
    best aviation academy in chennai
    aviation institute in chennai

  66. Wonderful post. Thanks for taking time to share this information with us.

    Guest posting sites


  67. Thank you for taking the time to write about this much needed subject. I felt that your remarks on this technology is helpful and were especially timely.

    Right now, DevOps is currently a popular model currently organizations all over the world moving towards to it. Your post gave a clear idea about knowing the DevOps model and its importance.

    devops course fees in chennai | devops training in chennai with placement | devops training in chennai omr | best devops training in chennai quora | devops foundation certification chennai

  68. Thank u for this information

  69. it is really explainable very well and i got more information from your blog.
    data science training
    dataguard training

  70. Thanks for sharing this information... Conatct Veelead for SharePoint Migration Services

  71. Thanks for Sharing Your Information Time Just Went On reading Your ArticlePython Online Training

  72. Good job in presenting the correct content with the clear explanation. The content looks real with valid information. Good Work

    DevOps is currently a popular model currently organizations all over the world moving towards to it. Your post gave a clear idea about knowing the DevOps model and its importance.

    Good to learn about DevOps at this time.

    devops training in chennai | devops training in chennai with placement | devops training in chennai omr | devops training in velachery | devops training in chennai tambaram | devops institutes in chennai | devops certification in chennai | trending technologies list 2018

  73. Such a wonderful blog on Machine learning . Your blog have almost full information about Machine learning .Your content covered full topics of Machine learning that it cover from basic to higher level content of Machine learning . Requesting you to please keep updating the data about Machine learning in upcoming time if there is some addition.
    Thanks and Regards,
    Machine learning tuition in chennai
    Machine learning workshops in chennai
    Machine learning training with certification in chennai

  74. Outstanding blog thanks for sharing such wonderful blog with us ,after long time came across such knowlegeble blog. keep sharing such informative blog with us.

    Machine learning training in chennai
    machine learning course fees in chennai
    machine learning training center in chennai
    machine learning with python course in chennai

  75. Hi, Thanks for sharing nice information about Python like the way to update more information. Anyhave interesting to learn Digital Marketing Course in Ameerpet . Best institutes is Hyderabad Digital Marketing Institutes they provide all concepts SEO,SMM,SMO ADwords, Affiliate Marketing.

  76. Thanks for sharing. I really liked your post, keep sharing!!

    CEH Training In Hyderbad

  77. Good job in presenting the correct content with the clear explanation. The content looks real with valid information. Good Work

    DevOps is currently a popular model currently organizations all over the world moving towards to it. Your post gave a clear idea about knowing the DevOps model and its importance.

    Good to learn about DevOps at this time.

    devops training in chennai | devops training in chennai with placement | devops training in chennai omr | devops training in velachery | devops training in chennai tambaram | devops institutes in chennai | devops certification in chennai | trending technologies list 2018 | Top 100 DevOps Interview Questions and Answers


  78. Nice blog..! I really loved reading through this article... Thanks for sharing such an amazing post with us and keep blogging...
    data science online training
    best data science online training
    data science online training in Hyderabad
    data science online training in india

  79. Really useful information. Thank you so much for sharing.It will help everyone.Keep Post. RPA training in chennai | RPA training in Chennai with placement

  80. Hey thanks for this lovely content. I will definitely come back in future and watch fro more very interesting subject love it , as well as this looks good, check out Top 10 places to visit in Shimla

  81. Nice post. Thanks for sharing! I want people to know just how good this information is in your article. It’s interesting content and Great work.
    Thanks & Regards,
    VRIT Professionals,
    No.1 Leading Web Designing Training Institute In Chennai.

    And also those who are looking for
    Web Designing Training Institute in Chennai
    SEO Training Institute in Chennai
    Photoshop Training Institute in Chennai
    PHP & Mysql Training Institute in Chennai
    Android Training Institute in Chennai

  82. Thank you for your post. This is excellent information. It is amazing and wonderful to visit your site.
    Even we r on same page. could u just give a review.
    python online training
    Best python online training
    python online training in Hyderabad
    python online training in india

  83. thanks for Providing a Great Info
    anyone want to learn advance devops tools or devops online training visit:
    DevOps Training
    DevOps Online Training
    DevOps Training institute in Hyderabad
    DevOps Training in Ameerpet

  84. Thanks for sharing such a wonderful blog on Machine learning.This blog contains so much data about Machine learning ,like if anyone who is searching for the Machine learning data will easily grab the knowledge of Machine learning from this .Requested you to please keep sharing these type of useful content so that other can get benefit from your shared content.
    Thanks and Regards,
    Top institutes for machine learning in chennai
    best machine learning institute in chennai
    artificial intelligence and machine learning course in chennai

  85. This is the exact information I am been searching for, Thanks for sharing the required infos with the clear update and required points. To appreciate this I like to share some useful information regarding Microsoft Azure which is latest and newest,


    Azure Training in Chennai
    Azure Training Center in Chennai
    Best Azure Training in Chennai
    Azure Devops Training in Chenna
    Azure Training Institute in Chennai
    Azure Training in Chennai OMR
    Azure Training in Chennai Velachery
    Azure Online Training
    Azure Training in Chennai Credo Systemz

  86. It's interesting that many of the bloggers to helped clarify a few things for me as well as giving.
    Most of ideas can be nice content.The people to give them a good shake to get your point and across the command.
    rpa online training

  87. Thank you for sharing such great information very useful to us.
    Python Training in Gurgaon

  88. A universal message I suppose, not giving up is the formula for success I think. Some things take longer than others to accomplish, so people must understand that they should have their eyes on the goal, and that should keep them motivated to see it out til the end.
    angularjs online training

    apache spark online training

    informatica mdm online training

    devops online training

    aws online training

  89. This comment has been removed by the author.

  90. It's a Very informative blog and useful article thank you for sharing with us, keep posting learn more about BI Tools Thanks for sharing valuable information. Your blogs were helpful to tableau learners. I request to update the blog through step-by-step. Also, find Technology news at
    Tableau Training

    Android Online Training

    Data Science Certification

    Dot net Training in bangalore


  91. It is amazing and wonderful to visit your site.Thanks for sharing this information,this is useful to me...

    Article submission sites

  92. Thanks For Sharing The Information The Information Shared Is Very Valuable Please Keep Updating Us Time Just Went On Reading The article Python Online Course

  93. Nice post. I learned some new information. Thanks for sharing.

    Guest posting sites

  94. Nice blog, thanks for sharing. Please Update more blog about this, this is really informative for me as well. Visit for Website Designing Services at Ogen Infosystem.
    Website Development Company in Delhi

  95. Thank you so much for given such an informative blog. Get the best Website Designing and Development Services by Ogeninfo.
    Website Designing Company in Delhi

  96. Options now contain versions for manufacturers, wholesalers, professional firms, contractors and non-profit entities. And retailers, in contributing to one precisely made for professional accounting firms who service numerous small enterprise clients. In May 2002 Intuit thrown QuickBooks Enterprise Solutions for medium-sized businesses. QuickBooks Customer Support Number here to provide tech support team to users.

  97. Nice blog, Get the mutual fund benefits and there investment schemes at Mutual Fund Wala.
    Best Performing Mutual Fund

  98. I like your blog, I read this blog please update more content on python, further check it once at python online course.

    Python Online Training

    Python Training

  99. Keep more update, I’ll wait for your next blog information. Thank you so much for sharing with us.
    Lifestyle Magazine India

  100. QuickBooks Payroll Support Phone Number and Full-service payroll are encompassed in Online Payroll whereas Basic, Enhanced and Assisted Payroll come under Payroll for Desktop.