From BlenderWiki

Jump to: navigation, search

A working Python example

Now that you’ve seen that Blender is extensible via Python scripting and that you’ve got the basics of script handling and how to run a script, before smashing your brain with the full python API reference, let’s have a look at a quick working example.

We will present a tiny script to produce polygons. This indeed duplicates somewhat the Space → Add → Mesh → Circle toolbox option, but will create “filled” polygons, not just the outline.

To make the script simple yet complete it will exhibit a Graphical User Interface (GUI) completely written via Blender’s API.

Headers, importing modules and globals

The first 30 lines of code are listed below:

Script header

  1. ######################################################
  2. #
  3. # Demo Script for Blender 2.3 Guide
  4. #
  5. ###################################################S68
  6. # This script generates polygons. It is quite useless
  7. # since you can do polygons with ADD->Mesh->Circle
  8. # but it is a nice complete script example, and the
  9. # polygons are 'filled'
  10. ######################################################
  11.  
  12. ######################################################
  13. # Importing modules
  14. ######################################################
  15.  
  16. import Blender
  17. from Blender import NMesh
  18. from Blender.BGL import *
  19. from Blender.Draw import *
  20.  
  21. import math
  22.  
  23. # Polygon Parameters
  24. T_NumberOfSides = Create(3)
  25. T_Radius = Create(1.0)
  26.  
  27. # Events
  28. EVENT_NOEVENT = 1
  29. EVENT_DRAW = 2
  30. EVENT_EXIT = 3

After the necessary comments with the description of what the script does there is (lines [016-021]) the importing of Python modules. Blender is the main Blender Python API module. NMesh is the module providing access to Blender’s meshes, while BGL and Draw give access to the OpenGL constants and functions and to Blender’s windowing interface, respectively.

The math module is Python’s mathematical module, but since both the math and the os modules are built into Blender you don’t need a full Python install for this!

The polygons are defined via the number of sides they have and their radius. These parameters have values which must be defined by the user via the GUI, hence lines [024-025] create two “generic button” objects, with their default starting value.

Finally, the GUI objects works with, and generates, events. Events identifier (or events ID for short) are integers left to the coder to define (they should all be different, unless special needs!). It is usually a good practice to define mnemonic names for events, as is done here in lines [028-030].

Drawing the GUI

The code responsible for drawing the GUI should reside in a draw function (GUI drawing).

GUI drawing

  1. ######################################################
  2. # GUI drawing
  3. ######################################################
  4. def draw():
  5.         global T_NumberOfSides
  6.         global T_Radius
  7.  
  8.         ########## Titles
  9.         glClear(GL_COLOR_BUFFER_BIT)
  10.         glRasterPos2d(8, 103)
  11.         Text("Demo Polygon Script")
  12.  
  13.         ######### Parameters GUI Buttons
  14.         glRasterPos2d(8, 83)
  15.         Text("Parameters:")
  16.         T_NumberOfSides = Number("No. of sides: ", EVENT_NOEVENT, 10, 55, 210, 18,
  17.                 T_NumberOfSides.val, 3, 20, "Number of sides of out polygon");
  18.         T_Radius = Slider("Radius: ", EVENT_NOEVENT, 10, 35, 210, 18,
  19.                 T_Radius.val, 0.001, 20.0, 1, "Radius of the polygon");
  20.  
  21.         ######### Draw and Exit Buttons
  22.         Button("Draw",EVENT_DRAW , 10, 10, 80, 18)
  23.         Button("Exit",EVENT_EXIT , 140, 10, 80, 18)

Lines [036-038] merely grant access to global data. The real interesting stuff starts from lines [041-043]. The OpenGL window is initialized, and the current position set to (x=8, y=103). The origin of this reference is the lower left corner of the script window. Then the title “Demo Polygon Script” is printed. A further string is written (lines [047-048]).

Then the input buttons for the parameters are created. The first (lines [048-049]) is a Num Button, exactly like those in the various Blender Button Windows. For the meaning of all the parameters please refer to the API reference. Basically there is the button label, the event generated by the button, its location (x,y) and its dimensions (width, height), its value, which is a data belonging to the Button object itself, the minimum and maximum allowable values and a text string which will appear as a help while hovering on the button, as a tooltip. Lines [050-051] defines a Num Button with a slider, with a very similar syntax. Lines [054-055] finally create a Draw button which will create the polygon and an Exit button.

Managing Events.

The GUI is not drawn, and will not work, until a proper event handler is written and registered (Handling events).

Handling events

  1. def event(evt, val):
  2.         if evt == QKEY and not val:
  3.                 Exit()
  4.  
  5. def bevent(evt):
  6.         ######### Manages GUI events
  7.         if evt == EVENT_EXIT:
  8.                 Exit()
  9.         elif evt == EVENT_DRAW:
  10.                 Polygon(T_NumberOfSides.val, T_Radius.val)
  11.                 Blender.Redraw()
  12.  
  13. Register(draw, event, bevent)

Lines [057-059] define the keyboard event handler, here responding to the Q with a plain Exit() call.

More interesting are lines [061-067], in charge of managing the GUI events. Every time a GUI button is used this function is called, with the event number defined within the button as a parameter. The core of this function is hence a “select” (if/elif) structure executing different codes according to the event number.

As a last call, the Register() function is invoked. This effectively draws the GUI and starts the event capturing cycle (“event loop”).

Mesh handling

Finally, Main function shows the main function, the one creating the polygon. It is a rather simple mesh editing, but shows many important points of the Blender’s internal data structure.

Main function

  1. ######################################################
  2. # Main Body
  3. ######################################################
  4. def Polygon(NumberOfSides,Radius):
  5.  
  6.         ######### Creates a new mesh
  7.         poly = NMesh.GetRaw()
  8.  
  9.         ######### Populates it of vertices
  10.         for i in range(0,NumberOfSides):
  11.                 phi = math.pi * 2 * i / NumberOfSides
  12.                 x = Radius * math.cos(phi)
  13.                 y = Radius * math.sin(phi)
  14.                 z = 0
  15.  
  16.                 v = NMesh.Vert(x,y,z)
  17.                 poly.verts.append(v)
  18.  
  19.         ######### Adds a new vertex to the center
  20.         v = NMesh.Vert(0.,0.,0.)
  21.         poly.verts.append(v)
  22.  
  23.         ######### Connects the vertices to form faces
  24.         for i in range(0,NumberOfSides):
  25.                 f = NMesh.Face()
  26.                 f.v.append(poly.verts[i])
  27.                 f.v.append(poly.verts[(i+1)%NumberOfSides])
  28.                 f.v.append(poly.verts[NumberOfSides])
  29.                 poly.faces.append(f)
  30.  
  31.         ######### Creates a new Object with the new Mesh
  32.         polyObj = NMesh.PutRaw(poly)
  33.  
  34.         Blender.Redraw()

The first important line here is number [080]. Here a new mesh object, poly is created. The mesh object is constituted of a list of vertices and a list of faces, plus some other interesting stuff. For our purposes the vertices and faces lists are what we need.

Of course the newly created mesh is empty. The first cycle (lines [083-090]) computes the x,y,z location of the NumberOfSides vertices needed to define the polygon. Being a flat figure it is z=0 for all. Line [089] calls the NMesh method Vert() to create a new vertex object of co-ordinates (x,y,z). Such an object is then appended (line [090]) in the poly Mesh verts list.

Finally (lines [093-094]) a last vertex is added in the centre.

Lines [097-102] now connect these vertices to make faces. It is not required to create all vertices beforehand and then faces. You can safely create a new face as soon as all its vertices are there.

Line [98] creates a new face object. A face object has its own list of vertices v (up to 4) defining it.

Lines [99-101] appends three vertices to the originally empty f.v list. The vertices are two subsequent vertices of the polygon and the central vertex. These vertices must be taken from the Mesh verts list.

Finally line [102] appends the newly created face to the faces list of our poly mesh.

Conclusions

The GUI of our example.
The result of our example script.

If you create a polygon.py file containing the above described code and load it into a Blender text window, as you learned in the previous page, and press AltP in that window to run it, you will see the script disappearing and the window turn grey. In the lower left corner the GUI will be drawn (The GUI of our example).

By selecting, for example, 5 vertices and a radius 0.5, and by pressing the Draw button a pentagon will appear on the xy plane of the 3D window (The result of our example script).