~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to doc/python_api/rst/info_tutorial_addon.rst

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-03-06 12:08:47 UTC
  • mfrom: (1.5.1) (14.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20130306120847-frjfaryb2zrotwcg
Tags: 2.66a-1ubuntu1
* Resynchronize with Debian (LP: #1076930, #1089256, #1052743, #999024,
  #1122888, #1147084)
* debian/control:
  - Lower build-depends on libavcodec-dev since we're not
    doing the libav9 transition in Ubuntu yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
Addon Tutorial
 
3
##############
 
4
 
 
5
************
 
6
Introduction
 
7
************
 
8
 
 
9
 
 
10
Intended Audience
 
11
=================
 
12
 
 
13
This tutorial is designed to help technical artists or developers learn to extend Blender.
 
14
An understanding of the basics of Python is expected for those working through this tutorial.
 
15
 
 
16
 
 
17
Prerequisites
 
18
-------------
 
19
 
 
20
Before going through the tutorial you should...
 
21
 
 
22
* Familiarity with the basics of working in Blender.
 
23
 
 
24
* Know how to run a script in Blender's text editor (as documented in the quick-start)
 
25
 
 
26
* Have an understanding of Python primitive types (int, boolean, string, list, tuple, dictionary, and set).
 
27
 
 
28
* Be familiar with the concept of Python modules.
 
29
 
 
30
* Basic understanding of classes (object orientation) in Python.
 
31
 
 
32
 
 
33
Suggested reading before starting this tutorial.
 
34
 
 
35
* `Dive Into Python <http://getpython3.com/diveintopython3/index.html>`_ sections (1, 2, 3, 4, and 7).
 
36
* :ref:`Blender API Quickstart <info_quickstart>`
 
37
  to help become familiar with Blender/Python basics.
 
38
 
 
39
 
 
40
To best troubleshoot any error message Python prints while writing scripts you run blender with from a terminal,
 
41
see :ref:`Use The Terminal <use_the_terminal>`.
 
42
 
 
43
Documentation Links
 
44
===================
 
45
 
 
46
While going through the tutorial you may want to look into our reference documentation.
 
47
 
 
48
* :ref:`Blender API Overview <info_overview>`. -
 
49
  *This document is rather detailed but helpful if you want to know more on a topic.*
 
50
 
 
51
* :mod:`bpy.context` api reference. -
 
52
  *Handy to have a list of available items your script may operate on.*
 
53
 
 
54
* :class:`bpy.types.Operator`. -
 
55
  *The following addons define operators, these docs give details and more examples of operators.*
 
56
 
 
57
 
 
58
******
 
59
Addons
 
60
******
 
61
 
 
62
 
 
63
What is an Addon?
 
64
=================
 
65
 
 
66
An addon is simply a Python module with some additional requirements so Blender can display it in a list with useful
 
67
information.
 
68
 
 
69
To give an example, here is the simplest possible addon.
 
70
 
 
71
 
 
72
.. code-block:: python
 
73
 
 
74
   bl_info = {"name": "My Test Addon", "category": "Object"}
 
75
   def register():
 
76
       print("Hello World")
 
77
   def unregister():
 
78
       print("Goodbye World")
 
79
 
 
80
 
 
81
* ``bl_info`` is a dictionary containing addon meta-data such as the title, version and author to be displayed in the
 
82
  user preferences addon list.
 
83
* ``register`` is a function which only runs when enabling the addon, this means the module can be loaded without
 
84
  activating the addon.
 
85
* ``unregister`` is a function to unload anything setup by ``register``, this is called when the addon is disabled.
 
86
 
 
87
 
 
88
 
 
89
Notice this addon does not do anything related to Blender, (the :mod:`bpy` module is not imported for example).
 
90
 
 
91
This is a contrived example of an addon that serves to illustrate the point
 
92
that the base requirements of an addon are simple.
 
93
 
 
94
An addon will typically register operators, panels, menu items etc, but its worth noting that _any_ script can do this,
 
95
when executed from the text editor or even the interactive console - there is nothing inherently different about an
 
96
addon that allows it to integrate with Blender, such functionality is just provided by the :mod:`bpy` module for any
 
97
script to access.
 
98
 
 
99
So an addon is just a way to encapsulate a Python module in a way a user can easily utilize.
 
100
 
 
101
.. note::
 
102
 
 
103
   Running this script within the text editor won't print anything,
 
104
   to see the output it must be installed through the user preferences.
 
105
   Messages will be printed when enabling and disabling.
 
106
 
 
107
 
 
108
Your First Addon
 
109
================
 
110
 
 
111
The simplest possible addon above was useful as an example but not much else.
 
112
This next addon is simple but shows how to integrate a script into Blender using an ``Operator``
 
113
which is the typical way to define a tool accessed from menus, buttons and keyboard shortcuts.
 
114
 
 
115
For the first example we'll make a script that simply moves all objects in a scene.
 
116
 
 
117
 
 
118
Write The Script
 
119
----------------
 
120
 
 
121
Add the following script to the text editor in Blender.
 
122
 
 
123
.. code-block:: python
 
124
 
 
125
   import bpy
 
126
 
 
127
   scene = bpy.context.scene
 
128
   for obj in scene.objects:
 
129
       obj.location.x += 1.0
 
130
 
 
131
 
 
132
.. image:: run_script.png
 
133
   :width: 924px
 
134
   :align: center
 
135
   :height: 574px
 
136
   :alt: Run Script button
 
137
 
 
138
Click the Run Script button, all objects in the active scene are moved by 1.0 Blender unit.
 
139
Next we'll make this script into an addon.
 
140
 
 
141
 
 
142
Write the Addon (Simple)
 
143
------------------------
 
144
 
 
145
This addon takes the body of the script above, and adds them to an operator's ``execute()`` function.
 
146
 
 
147
 
 
148
.. code-block:: python
 
149
 
 
150
   bl_info = {
 
151
       "name": "Move X Axis",
 
152
       "category": "Object",
 
153
   }
 
154
 
 
155
   import bpy
 
156
 
 
157
 
 
158
   class ObjectMoveX(bpy.types.Operator):
 
159
       """My Object Moving Script"""      # blender will use this as a tooltip for menu items and buttons.
 
160
       bl_idname = "object.move_x"        # unique identifier for buttons and menu items to reference.
 
161
       bl_label = "Move X by One"         # display name in the interface.
 
162
       bl_options = {'REGISTER', 'UNDO'}  # enable undo for the operator.
 
163
 
 
164
       def execute(self, context):        # execute() is called by blender when running the operator.
 
165
 
 
166
           # The original script
 
167
           scene = context.scene
 
168
           for obj in scene.objects:
 
169
               obj.location.x += 1.0
 
170
 
 
171
           return {'FINISHED'}            # this lets blender know the operator finished successfully.
 
172
 
 
173
   def register():
 
174
       bpy.utils.register_class(ObjectMoveX)
 
175
 
 
176
 
 
177
   def unregister():
 
178
       bpy.utils.unregister_class(ObjectMoveX)
 
179
 
 
180
 
 
181
   # This allows you to run the script directly from blenders text editor
 
182
   # to test the addon without having to install it.
 
183
   if __name__ == "__main__":
 
184
       register()
 
185
 
 
186
 
 
187
.. note:: ``bl_info`` is split across multiple lines, this is just a style convention used to more easily add items.
 
188
 
 
189
.. note:: Rather than using ``bpy.context.scene``, we use the ``context.scene`` argument passed to ``execute()``.
 
190
          In most cases these will be the same however in some cases operators will be passed a custom context
 
191
          so script authors should prefer the ``context`` argument passed to operators.
 
192
   
 
193
 
 
194
To test the script you can copy and paste this into Blender text editor and run it, this will execute the script
 
195
directly and call register immediately.
 
196
 
 
197
However running the script wont move any objects, for this you need to execute the newly registered operator.
 
198
 
 
199
.. image:: spacebar.png
 
200
   :width: 924px
 
201
   :align: center
 
202
   :height: 574px
 
203
   :alt: Spacebar
 
204
 
 
205
Do this by pressing ``SpaceBar`` to bring up the operator search dialog and type in "Move X by One" (the ``bl_label``),
 
206
then press ``Enter``.
 
207
 
 
208
 
 
209
 
 
210
The objects should move as before.
 
211
 
 
212
*Keep this addon open in Blender for the next step - Installing.*
 
213
 
 
214
Install The Addon
 
215
-----------------
 
216
 
 
217
Once you have your addon within in Blender's text editor, you will want to be able to install it so it can be enabled in
 
218
the user preferences to load on startup.
 
219
 
 
220
Even though the addon above is a test, lets go through the steps anyway so you know how to do it for later.
 
221
 
 
222
To install the Blender text as an addon you will first have to save it to disk, take care to obey the naming
 
223
restrictions that apply to Python modules and end with a ``.py`` extension.
 
224
 
 
225
Once the file is on disk, you can install it as you would for an addon downloaded online.
 
226
 
 
227
Open the user **File -> User Preferences**, Select the **Addon** section, press **Install Addon...** and select the file. 
 
228
 
 
229
Now the addon will be listed and you can enable it by pressing the check-box, if you want it to be enabled on restart,
 
230
press **Save as Default**.
 
231
 
 
232
.. note::
 
233
 
 
234
   The destination of the addon depends on your Blender configuration.
 
235
   When installing an addon the source and destination path are printed in the console.
 
236
   You can also find addon path locations by running this in the Python console.
 
237
 
 
238
   .. code-block:: python
 
239
 
 
240
      import addon_utils
 
241
      print(addon_utils.paths())
 
242
 
 
243
   More is written on this topic here:
 
244
   `Directory Layout <http://wiki.blender.org/index.php/Doc:2.6/Manual/Introduction/Installing_Blender/DirectoryLayout>`_
 
245
 
 
246
 
 
247
Your Second Addon
 
248
=================
 
249
 
 
250
For our second addon, we will focus on object instancing - this is - to make linked copies of an object in a
 
251
similar way to what you may have seen with the array modifier.
 
252
 
 
253
 
 
254
Write The Script
 
255
----------------
 
256
 
 
257
As before, first we will start with a script, develop it, then convert into an addon.
 
258
 
 
259
.. code-block:: python
 
260
 
 
261
   import bpy
 
262
   from bpy import context
 
263
 
 
264
   # Get the current scene
 
265
   scene = context.scene
 
266
 
 
267
   # Get the 3D cursor
 
268
   cursor = scene.cursor_location
 
269
 
 
270
   # Get the active object (assume we have one)
 
271
   obj = scene.objects.active
 
272
 
 
273
   # Now make a copy of the object
 
274
   obj_new = obj.copy()
 
275
 
 
276
   # The object won't automatically get into a new scene
 
277
   scene.objects.link(obj_new)
 
278
 
 
279
   # Now we can place the object
 
280
   obj_new.location = cursor
 
281
 
 
282
 
 
283
Now try copy this script into Blender and run it on the default cube.
 
284
Make sure you click to move the 3D cursor before running as the duplicate will appear at the cursor's location.
 
285
 
 
286
 
 
287
... go off and test ...
 
288
 
 
289
 
 
290
After running, notice that when you go into edit-mode to change the cube - all of the copies change,
 
291
in Blender this is known as *Linked-Duplicates*.
 
292
 
 
293
 
 
294
Next, we're going to do this in a loop, to make an array of objects between the active object and the cursor.
 
295
 
 
296
 
 
297
.. code-block:: python
 
298
 
 
299
   import bpy
 
300
   from bpy import context
 
301
 
 
302
   scene = context.scene
 
303
   cursor = scene.cursor_location
 
304
   obj = scene.objects.active
 
305
 
 
306
   # Use a fixed value for now, eventually make this user adjustable
 
307
   total = 10
 
308
 
 
309
   # Add 'total' objects into the scene
 
310
   for i in range(total):
 
311
       obj_new = obj.copy()
 
312
       scene.objects.link(obj_new)
 
313
 
 
314
       # Now place the object in between the cursor
 
315
       # and the active object based on 'i'
 
316
       factor = i / total
 
317
       obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
 
318
 
 
319
 
 
320
Try run this script with with the active object and the cursor spaced apart to see the result.
 
321
 
 
322
With this script you'll notice we're doing some math with the object location and cursor, this works because both are
 
323
3D :class:`mathutils.Vector` instances, a convenient class provided by the :mod:`mathutils` module and
 
324
allows vectors to be multiplied by numbers and matrices.
 
325
 
 
326
If you are interested in this area, read into :class:`mathutils.Vector` - there are many handy utility functions
 
327
such as getting the angle between vectors, cross product, dot products
 
328
as well as more advanced functions in :mod:`mathutils.geometry` such as bezier spline interpolation and
 
329
ray-triangle intersection.
 
330
 
 
331
For now we'll focus on making this script an addon, but its good to know that this 3D math module is available and
 
332
can help you with more advanced functionality later on.
 
333
 
 
334
 
 
335
Write the Addon
 
336
---------------
 
337
 
 
338
The first step is to convert the script as-is into an addon.
 
339
 
 
340
 
 
341
.. code-block:: python
 
342
 
 
343
   bl_info = {
 
344
       "name": "Cursor Array",
 
345
       "category": "Object",
 
346
   }
 
347
 
 
348
   import bpy
 
349
 
 
350
 
 
351
   class ObjectCursorArray(bpy.types.Operator):
 
352
       """Object Cursor Array"""
 
353
       bl_idname = "object.cursor_array"
 
354
       bl_label = "Cursor Array"
 
355
       bl_options = {'REGISTER', 'UNDO'}
 
356
 
 
357
       def execute(self, context):
 
358
           scene = context.scene
 
359
           cursor = scene.cursor_location
 
360
           obj = scene.objects.active
 
361
 
 
362
           total = 10
 
363
 
 
364
           for i in range(total):
 
365
               obj_new = obj.copy()
 
366
               scene.objects.link(obj_new)
 
367
 
 
368
               factor = i / total
 
369
               obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
 
370
 
 
371
           return {'FINISHED'}
 
372
 
 
373
   def register():
 
374
       bpy.utils.register_class(ObjectCursorArray)
 
375
 
 
376
 
 
377
   def unregister():
 
378
       bpy.utils.unregister_class(ObjectCursorArray)
 
379
 
 
380
 
 
381
   if __name__ == "__main__":
 
382
       register()
 
383
 
 
384
 
 
385
Everything here has been covered in the previous steps, you may want to try run the addon still
 
386
and consider what could be done to make it more useful.
 
387
 
 
388
 
 
389
... go off and test ...
 
390
 
 
391
 
 
392
The two of the most obvious missing things are - having the total fixed at 10, and having to access the operator from
 
393
space-bar is not very convenient.
 
394
 
 
395
Both these additions are explained next, with the final script afterwards.
 
396
 
 
397
 
 
398
Operator Property
 
399
^^^^^^^^^^^^^^^^^
 
400
 
 
401
There are a variety of property types that are used for tool settings, common property types include:
 
402
int, float, vector, color, boolean and string.
 
403
 
 
404
These properties are handled differently to typical Python class attributes
 
405
because Blender needs to be display them in the interface,
 
406
store their settings in key-maps and keep settings for re-use.
 
407
 
 
408
While this is handled in a fairly Pythonic way, be mindful that you are in fact defining tool settings that
 
409
are loaded into Blender and accessed by other parts of Blender, outside of Python.
 
410
 
 
411
 
 
412
To get rid of the literal 10 for `total`, we'll us an operator property.
 
413
Operator properties are defined via bpy.props module, this is added to the class body.
 
414
 
 
415
.. code-block:: python
 
416
 
 
417
   # moved assignment from execute() to the body of the class...
 
418
   total = bpy.props.IntProperty(name="Steps", default=2, min=1, max=100)
 
419
 
 
420
   # and this is accessed on the class
 
421
   # instance within the execute() function as...
 
422
   self.total
 
423
 
 
424
 
 
425
These properties from :mod:`bpy.props` are handled specially by Blender when the class is registered
 
426
so they display as buttons in the user interface.
 
427
There are many arguments you can pass to properties to set limits, change the default and display a tooltip.
 
428
 
 
429
.. seealso:: :mod:`bpy.props.IntProperty`
 
430
 
 
431
This document doesn't go into details about using other property types,
 
432
however the link above includes examples of more advanced property usage.
 
433
 
 
434
 
 
435
Menu Item
 
436
^^^^^^^^^
 
437
 
 
438
Addons can add to the user interface of existing panels, headers and menus defined in Python.
 
439
 
 
440
For this example we'll add to an existing menu.
 
441
 
 
442
.. image:: menu_id.png
 
443
   :width: 334px
 
444
   :align: center
 
445
   :height: 128px
 
446
   :alt: Menu Identifier
 
447
 
 
448
To find the identifier of a menu you can hover your mouse over the menu item and the identifier is displayed.
 
449
 
 
450
The method used for adding a menu item is to append a draw function into an existing class.
 
451
 
 
452
 
 
453
.. code-block:: python
 
454
 
 
455
   def menu_func(self, context):
 
456
       self.layout.operator(ObjectCursorArray.bl_idname)
 
457
 
 
458
   def register():
 
459
       bpy.types.VIEW3D_MT_object.append(menu_func)
 
460
 
 
461
 
 
462
For docs on extending menus see: :doc:`bpy.types.Menu`.
 
463
 
 
464
 
 
465
Keymap
 
466
^^^^^^
 
467
 
 
468
In Blender addons have their own key-maps so as not to interfere with Blenders built in key-maps.
 
469
 
 
470
In the example below, a new object-mode :class:`bpy.types.KeyMap` is added,
 
471
then a :class:`bpy.types.KeyMapItem` is added to the key-map which references our newly added operator,
 
472
using :kbd:`Ctrl-Shift-Space` as the key shortcut to activate it.
 
473
 
 
474
 
 
475
.. code-block:: python
 
476
 
 
477
   # store keymaps here to access after registration
 
478
   addon_keymaps = []
 
479
 
 
480
   def register():
 
481
 
 
482
       # handle the keymap
 
483
       wm = bpy.context.window_manager
 
484
       km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
 
485
 
 
486
       kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
 
487
       kmi.properties.total = 4
 
488
 
 
489
       addon_keymaps.append((km, kmi))
 
490
 
 
491
 
 
492
   def unregister():
 
493
 
 
494
       # handle the keymap
 
495
       for km, kmi in addon_keymaps:
 
496
           km.keymap_items.remove(kmi)
 
497
       addon_keymaps.clear()
 
498
 
 
499
 
 
500
Notice how the key-map item can have a different ``total`` setting then the default set by the operator,
 
501
this allows you to have multiple keys accessing the same operator with different settings.
 
502
 
 
503
 
 
504
.. note::
 
505
 
 
506
   While :kbd:`Ctrl-Shift-Space` isn't a default Blender key shortcut, its hard to make sure addons won't
 
507
   overwrite each others keymaps, At least take care when assigning keys that they don't
 
508
   conflict with important functionality within Blender.
 
509
 
 
510
For API documentation on the functions listed above, see:
 
511
:class:`bpy.types.KeyMaps.new`,
 
512
:class:`bpy.types.KeyMap`,
 
513
:class:`bpy.types.KeyMapItems.new`,
 
514
:class:`bpy.types.KeyMapItem`.
 
515
 
 
516
 
 
517
Bringing it all together
 
518
^^^^^^^^^^^^^^^^^^^^^^^^
 
519
 
 
520
.. code-block:: python
 
521
 
 
522
   bl_info = {
 
523
       "name": "Cursor Array",
 
524
       "category": "Object",
 
525
   }
 
526
 
 
527
   import bpy
 
528
 
 
529
 
 
530
   class ObjectCursorArray(bpy.types.Operator):
 
531
       """Object Cursor Array"""
 
532
       bl_idname = "object.cursor_array"
 
533
       bl_label = "Cursor Array"
 
534
       bl_options = {'REGISTER', 'UNDO'}
 
535
 
 
536
       total = bpy.props.IntProperty(name="Steps", default=2, min=1, max=100)
 
537
 
 
538
       def execute(self, context):
 
539
           scene = context.scene
 
540
           cursor = scene.cursor_location
 
541
           obj = scene.objects.active
 
542
 
 
543
           for i in range(self.total):
 
544
               obj_new = obj.copy()
 
545
               scene.objects.link(obj_new)
 
546
 
 
547
               factor = i / self.total
 
548
               obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
 
549
 
 
550
           return {'FINISHED'}
 
551
 
 
552
 
 
553
   def menu_func(self, context):
 
554
       self.layout.operator(ObjectCursorArray.bl_idname)
 
555
 
 
556
   # store keymaps here to access after registration
 
557
   addon_keymaps = []
 
558
 
 
559
 
 
560
   def register():
 
561
       bpy.utils.register_class(ObjectCursorArray)
 
562
       bpy.types.VIEW3D_MT_object.append(menu_func)
 
563
 
 
564
       # handle the keymap
 
565
       wm = bpy.context.window_manager
 
566
       km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
 
567
       kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
 
568
       kmi.properties.total = 4
 
569
       addon_keymaps.append((km, kmi))
 
570
 
 
571
   def unregister():
 
572
       bpy.utils.unregister_class(ObjectCursorArray)
 
573
       bpy.types.VIEW3D_MT_object.remove(menu_func)
 
574
 
 
575
       # handle the keymap
 
576
       for km, kmi in addon_keymaps:
 
577
           km.keymap_items.remove(kmi)
 
578
       addon_keymaps.clear()
 
579
 
 
580
 
 
581
   if __name__ == "__main__":
 
582
       register()
 
583
 
 
584
.. image:: in_menu.png
 
585
   :width: 591px
 
586
   :align: center
 
587
   :height: 649px
 
588
   :alt: In the menu
 
589
 
 
590
Run the script (or save it and add it through the Preferences like before) and it will appear in the menu.
 
591
 
 
592
.. image:: op_prop.png
 
593
   :width: 669px
 
594
   :align: center
 
595
   :height: 644px
 
596
   :alt: Operator Property
 
597
 
 
598
After selecting it from the menu, you can choose how many instance of the cube you want created.
 
599
 
 
600
 
 
601
.. note::
 
602
 
 
603
   Directly executing the script multiple times will add the menu each time too.
 
604
   While not useful behavior, theres nothing to worry about since addons won't register them selves multiple
 
605
   times when enabled through the user preferences.
 
606
 
 
607
 
 
608
Conclusions
 
609
===========
 
610
 
 
611
Addons can encapsulate certain functionality neatly for writing tools to improve your work-flow or for writing utilities
 
612
for others to use.
 
613
 
 
614
While there are limits to what Python can do within Blender, there is certainly a lot that can be achieved without
 
615
having to dive into Blender's C/C++ code.
 
616
 
 
617
The example given in the tutorial is limited, but shows the Blender API used for common tasks that you can expand on
 
618
to write your own tools.
 
619
 
 
620
 
 
621
Further Reading
 
622
---------------
 
623
 
 
624
Blender comes commented templates which are accessible from the text editor header, if you have specific areas
 
625
you want to see example code for, this is a good place to start.
 
626
 
 
627
 
 
628
Here are some sites you might like to check on after completing this tutorial.
 
629
 
 
630
* :ref:`Blender/Python API Overview <info_overview>` -
 
631
  *For more background details on Blender/Python integration.*
 
632
 
 
633
* `How to Think Like a Computer Scientist <http://interactivepython.org/courselib/static/thinkcspy/index.html>`_ -
 
634
  *Great info for those who are still learning Python.*
 
635
 
 
636
* `Blender Development (Wiki) <http://wiki.blender.org/index.php/Dev:Contents>`_ -
 
637
  *Blender Development, general information and helpful links.*
 
638
 
 
639
* `Blender Artists (Coding Section) <http://blenderartists.org/forum/forumdisplay.php?47-Coding>`_ -
 
640
  *forum where people ask Python development questions*
 
641