Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorAaron Carlisle <carlisle.b3d@gmail.com>2017-06-15 20:00:58 +0300
committerAaron Carlisle <carlisle.b3d@gmail.com>2017-06-16 05:01:03 +0300
commit127a754615efff02669a9afb50c2d44f6b354403 (patch)
tree9032331459099289632042e4c7f79fb999bcf44a /doc
parent6b502731a50d22d8d2b4efb81908ec0616a66d5d (diff)
PyAPI: Remove addon tutorial
This page now lives at https://docs.blender.org/manual/en/dev/advanced/scripting/addon_tutorial.html
Diffstat (limited to 'doc')
-rw-r--r--doc/python_api/rst/info_tutorial_addon.rst635
-rw-r--r--doc/python_api/sphinx_doc_gen.py5
2 files changed, 3 insertions, 637 deletions
diff --git a/doc/python_api/rst/info_tutorial_addon.rst b/doc/python_api/rst/info_tutorial_addon.rst
deleted file mode 100644
index 92fbf9b8787..00000000000
--- a/doc/python_api/rst/info_tutorial_addon.rst
+++ /dev/null
@@ -1,635 +0,0 @@
-
-Add-on Tutorial
-###############
-
-************
-Introduction
-************
-
-
-Intended Audience
-=================
-
-This tutorial is designed to help technical artists or developers learn to extend Blender.
-An understanding of the basics of Python is expected for those working through this tutorial.
-
-
-Prerequisites
--------------
-
-Before going through the tutorial you should...
-
-- Familiarity with the basics of working in Blender.
-- Know how to run a script in Blender's text editor (as documented in the quick-start)
-- Have an understanding of Python primitive types (int, boolean, string, list, tuple, dictionary, and set).
-- Be familiar with the concept of Python modules.
-- Basic understanding of classes (object orientation) in Python.
-
-
-Suggested reading before starting this tutorial.
-
-- `Dive Into Python <http://getpython3.com/diveintopython3/index.html>`_ sections (1, 2, 3, 4, and 7).
-- :ref:`Blender API Quickstart <info_quickstart>`
- to help become familiar with Blender/Python basics.
-
-
-To best troubleshoot any error message Python prints while writing scripts you run blender with from a terminal,
-see :ref:`Use The Terminal <use_the_terminal>`.
-
-
-Documentation Links
-===================
-
-While going through the tutorial you may want to look into our reference documentation.
-
-- :ref:`Blender API Overview <info_overview>`. -
- *This document is rather detailed but helpful if you want to know more on a topic.*
-- :mod:`bpy.context` api reference. -
- *Handy to have a list of available items your script may operate on.*
-- :class:`bpy.types.Operator`. -
- *The following add-ons define operators, these docs give details and more examples of operators.*
-
-
-*******
-Add-ons
-*******
-
-What is an Add-on?
-==================
-
-An add-on is simply a Python module with some additional requirements so Blender can display it in a list with useful
-information.
-
-To give an example, here is the simplest possible add-on.
-
-.. code-block:: python
-
- bl_info = {"name": "My Test Add-on", "category": "Object"}
- def register():
- print("Hello World")
- def unregister():
- print("Goodbye World")
-
-
-- ``bl_info`` is a dictionary containing add-on metadata such as the title,
- version and author to be displayed in the user preferences add-on list.
-- ``register`` is a function which only runs when enabling the add-on,
- this means the module can be loaded without activating the add-on.
-- ``unregister`` is a function to unload anything setup by ``register``, this is called when the add-on is disabled.
-
-
-Notice this add-on does not do anything related to Blender, (the :mod:`bpy` module is not imported for example).
-
-This is a contrived example of an add-on that serves to illustrate the point
-that the base requirements of an add-on are simple.
-
-An add-on will typically register operators, panels, menu items etc, but its worth noting that _any_ script can do this,
-when executed from the text editor or even the interactive console - there is nothing inherently different about an
-add-on that allows it to integrate with Blender, such functionality is just provided by the :mod:`bpy` module for any
-script to access.
-
-So an add-on is just a way to encapsulate a Python module in a way a user can easily utilize.
-
-.. note::
-
- Running this script within the text editor won't print anything,
- to see the output it must be installed through the user preferences.
- Messages will be printed when enabling and disabling.
-
-
-Your First Add-on
-=================
-
-The simplest possible add-on above is useful as an example but not much else.
-This next add-on is simple but shows how to integrate a script into Blender using an ``Operator``
-which is the typical way to define a tool accessed from menus, buttons and keyboard shortcuts.
-
-For the first example we will make a script that simply moves all objects in a scene.
-
-
-Write The Script
-----------------
-
-Add the following script to the text editor in Blender.
-
-.. code-block:: python
-
- import bpy
-
- scene = bpy.context.scene
- for obj in scene.objects:
- obj.location.x += 1.0
-
-
-Click the :ref:`Run Script button <blender_manual:editors-text-run-script>`,
-all objects in the active scene are moved by 1.0 Blender unit.
-
-
-Write the Add-on (Simple)
--------------------------
-
-This add-on takes the body of the script above, and adds them to an operator's ``execute()`` function.
-
-
-.. code-block:: python
-
- bl_info = {
- "name": "Move X Axis",
- "category": "Object",
- }
-
- import bpy
-
-
- class ObjectMoveX(bpy.types.Operator):
- """My Object Moving Script""" # blender will use this as a tooltip for menu items and buttons.
- bl_idname = "object.move_x" # unique identifier for buttons and menu items to reference.
- bl_label = "Move X by One" # display name in the interface.
- bl_options = {'REGISTER', 'UNDO'} # enable undo for the operator.
-
- def execute(self, context): # execute() is called by blender when running the operator.
-
- # The original script
- scene = context.scene
- for obj in scene.objects:
- obj.location.x += 1.0
-
- return {'FINISHED'} # this lets blender know the operator finished successfully.
-
- def register():
- bpy.utils.register_class(ObjectMoveX)
-
-
- def unregister():
- bpy.utils.unregister_class(ObjectMoveX)
-
-
- # This allows you to run the script directly from blenders text editor
- # to test the add-on without having to install it.
- if __name__ == "__main__":
- register()
-
-
-.. note::
-
- ``bl_info`` is split across multiple lines, this is just a style convention used to more easily add items.
-
-.. note::
-
- Rather than using ``bpy.context.scene``, we use the ``context.scene`` argument passed to ``execute()``.
- In most cases these will be the same however in some cases operators will be passed a custom context
- so script authors should prefer the ``context`` argument passed to operators.
-
-To test the script you can copy and paste this into Blender text editor and run it, this will execute the script
-directly and call register immediately.
-
-However running the script wont move any objects, for this you need to execute the newly registered operator.
-
-.. image:: spacebar.png
- :width: 924px
- :align: center
- :height: 574px
- :alt: Spacebar
-
-Do this by pressing :kbd:`Spacebar` to bring up the operator search dialog and type in
-"Move X by One" (the ``bl_label``), then :kbd:`Enter`.
-
-
-
-The objects should move as before.
-
-*Keep this add-on open in Blender for the next step - Installing.*
-
-
-Install The Add-on
-------------------
-
-Once you have your add-on within in Blender's text editor,
-you will want to be able to install it so it can be enabled in the user preferences to load on startup.
-
-Even though the add-on above is a test, lets go through the steps anyway so you know how to do it for later.
-
-To install the Blender text as an add-on you will first have to save it to disk, take care to obey the naming
-restrictions that apply to Python modules and end with a ``.py`` extension.
-
-Once the file is on disk, you can install it as you would for an add-on downloaded online.
-
-Open the user :menuselection:`File --> User Preferences`,
-Select the *Add-on* section, press *Install Add-on...* and select the file.
-
-Now the add-on will be listed and you can enable it by pressing the check-box,
-if you want it to be enabled on restart, press *Save as Default*.
-
-.. note::
-
- The destination of the add-on depends on your Blender configuration.
- When installing an add-on the source and destination path are printed in the console.
- You can also find add-on path locations by running this in the Python console.
-
- .. code-block:: python
-
- import addon_utils
- print(addon_utils.paths())
-
- More is written on this topic here:
- :ref:`Directory Layout <blender_manual:getting-started_installing-config-directories>`.
-
-
-Your Second Add-on
-==================
-
-For our second add-on, we will focus on object instancing - this is - to make linked copies of an object in a
-similar way to what you may have seen with the array modifier.
-
-
-Write The Script
-----------------
-
-As before, first we will start with a script, develop it, then convert into an add-on.
-
-.. code-block:: python
-
- import bpy
- from bpy import context
-
- # Get the current scene
- scene = context.scene
-
- # Get the 3D cursor
- cursor = scene.cursor_location
-
- # Get the active object (assume we have one)
- obj = scene.objects.active
-
- # Now make a copy of the object
- obj_new = obj.copy()
-
- # The object won't automatically get into a new scene
- scene.objects.link(obj_new)
-
- # Now we can place the object
- obj_new.location = cursor
-
-
-Now try copy this script into Blender and run it on the default cube.
-Make sure you click to move the 3D cursor before running as the duplicate will appear at the cursor's location.
-
-
-... go off and test ...
-
-
-After running, notice that when you go into edit-mode to change the cube - all of the copies change,
-in Blender this is known as *Linked-Duplicates*.
-
-
-Next, we're going to do this in a loop, to make an array of objects between the active object and the cursor.
-
-
-.. code-block:: python
-
- import bpy
- from bpy import context
-
- scene = context.scene
- cursor = scene.cursor_location
- obj = scene.objects.active
-
- # Use a fixed value for now, eventually make this user adjustable
- total = 10
-
- # Add 'total' objects into the scene
- for i in range(total):
- obj_new = obj.copy()
- scene.objects.link(obj_new)
-
- # Now place the object in between the cursor
- # and the active object based on 'i'
- factor = i / total
- obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
-
-
-Try run this script with with the active object and the cursor spaced apart to see the result.
-
-With this script you'll notice we're doing some math with the object location and cursor, this works because both are
-3D :class:`mathutils.Vector` instances, a convenient class provided by the :mod:`mathutils` module and
-allows vectors to be multiplied by numbers and matrices.
-
-If you are interested in this area, read into :class:`mathutils.Vector` - there are many handy utility functions
-such as getting the angle between vectors, cross product, dot products
-as well as more advanced functions in :mod:`mathutils.geometry` such as Bézier Spline interpolation and
-ray-triangle intersection.
-
-For now we will focus on making this script an add-on, but its good to know that this 3D math module is available and
-can help you with more advanced functionality later on.
-
-
-Write the Add-on
-----------------
-
-The first step is to convert the script as-is into an add-on.
-
-
-.. code-block:: python
-
- bl_info = {
- "name": "Cursor Array",
- "category": "Object",
- }
-
- import bpy
-
-
- class ObjectCursorArray(bpy.types.Operator):
- """Object Cursor Array"""
- bl_idname = "object.cursor_array"
- bl_label = "Cursor Array"
- bl_options = {'REGISTER', 'UNDO'}
-
- def execute(self, context):
- scene = context.scene
- cursor = scene.cursor_location
- obj = scene.objects.active
-
- total = 10
-
- for i in range(total):
- obj_new = obj.copy()
- scene.objects.link(obj_new)
-
- factor = i / total
- obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
-
- return {'FINISHED'}
-
- def register():
- bpy.utils.register_class(ObjectCursorArray)
-
-
- def unregister():
- bpy.utils.unregister_class(ObjectCursorArray)
-
-
- if __name__ == "__main__":
- register()
-
-
-Everything here has been covered in the previous steps, you may want to try run the add-on still
-and consider what could be done to make it more useful.
-
-
-... go off and test ...
-
-
-The two of the most obvious missing things are - having the total fixed at 10, and having to access the operator from
-space-bar is not very convenient.
-
-Both these additions are explained next, with the final script afterwards.
-
-
-Operator Property
-^^^^^^^^^^^^^^^^^
-
-There are a variety of property types that are used for tool settings, common property types include:
-int, float, vector, color, boolean and string.
-
-These properties are handled differently to typical Python class attributes
-because Blender needs to be display them in the interface,
-store their settings in key-maps and keep settings for re-use.
-
-While this is handled in a fairly Pythonic way, be mindful that you are in fact defining tool settings that
-are loaded into Blender and accessed by other parts of Blender, outside of Python.
-
-
-To get rid of the literal 10 for `total`, we'll us an operator property.
-Operator properties are defined via bpy.props module, this is added to the class body.
-
-.. code-block:: python
-
- # moved assignment from execute() to the body of the class...
- total = bpy.props.IntProperty(name="Steps", default=2, min=1, max=100)
-
- # and this is accessed on the class
- # instance within the execute() function as...
- self.total
-
-
-These properties from :mod:`bpy.props` are handled specially by Blender when the class is registered
-so they display as buttons in the user interface.
-There are many arguments you can pass to properties to set limits, change the default and display a tooltip.
-
-.. seealso:: :mod:`bpy.props.IntProperty`
-
-This document doesn't go into details about using other property types,
-however the link above includes examples of more advanced property usage.
-
-
-Menu Item
-^^^^^^^^^
-
-Add-ons can add to the user interface of existing panels, headers and menus defined in Python.
-
-For this example we'll add to an existing menu.
-
-.. image:: menu_id.png
- :width: 334px
- :align: center
- :height: 128px
- :alt: Menu Identifier
-
-To find the identifier of a menu you can hover your mouse over the menu item and the identifier is displayed.
-
-The method used for adding a menu item is to append a draw function into an existing class.
-
-
-.. code-block:: python
-
- def menu_func(self, context):
- self.layout.operator(ObjectCursorArray.bl_idname)
-
- def register():
- bpy.types.VIEW3D_MT_object.append(menu_func)
-
-
-For docs on extending menus see: :doc:`bpy.types.Menu`.
-
-
-Keymap
-^^^^^^
-
-In Blender, add-ons have their own keymaps so as not to interfere with Blenders built in key-maps.
-
-In the example below, a new object-mode :class:`bpy.types.KeyMap` is added,
-then a :class:`bpy.types.KeyMapItem` is added to the key-map which references our newly added operator,
-using :kbd:`Ctrl-Shift-Space` as the key shortcut to activate it.
-
-
-.. code-block:: python
-
- # store keymaps here to access after registration
- addon_keymaps = []
-
- def register():
-
- # handle the keymap
- wm = bpy.context.window_manager
- km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
-
- kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
- kmi.properties.total = 4
-
- addon_keymaps.append((km, kmi))
-
-
- def unregister():
-
- # handle the keymap
- for km, kmi in addon_keymaps:
- km.keymap_items.remove(kmi)
- addon_keymaps.clear()
-
-
-Notice how the key-map item can have a different ``total`` setting then the default set by the operator,
-this allows you to have multiple keys accessing the same operator with different settings.
-
-
-.. note::
-
- While :kbd:`Ctrl-Shift-Space` isn't a default Blender key shortcut, its hard to make sure add-ons won't
- overwrite each others keymaps, At least take care when assigning keys that they don't
- conflict with important functionality within Blender.
-
-For API documentation on the functions listed above, see:
-:class:`bpy.types.KeyMaps.new`,
-:class:`bpy.types.KeyMap`,
-:class:`bpy.types.KeyMapItems.new`,
-:class:`bpy.types.KeyMapItem`.
-
-
-Bringing it all together
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-.. code-block:: python
-
- bl_info = {
- "name": "Cursor Array",
- "category": "Object",
- }
-
- import bpy
-
-
- class ObjectCursorArray(bpy.types.Operator):
- """Object Cursor Array"""
- bl_idname = "object.cursor_array"
- bl_label = "Cursor Array"
- bl_options = {'REGISTER', 'UNDO'}
-
- total = bpy.props.IntProperty(name="Steps", default=2, min=1, max=100)
-
- def execute(self, context):
- scene = context.scene
- cursor = scene.cursor_location
- obj = scene.objects.active
-
- for i in range(self.total):
- obj_new = obj.copy()
- scene.objects.link(obj_new)
-
- factor = i / self.total
- obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
-
- return {'FINISHED'}
-
-
- def menu_func(self, context):
- self.layout.operator(ObjectCursorArray.bl_idname)
-
- # store keymaps here to access after registration
- addon_keymaps = []
-
-
- def register():
- bpy.utils.register_class(ObjectCursorArray)
- bpy.types.VIEW3D_MT_object.append(menu_func)
-
- # handle the keymap
- wm = bpy.context.window_manager
- # Note that in background mode (no GUI available), keyconfigs are not available either, so we have to check this
- # to avoid nasty errors in background case.
- kc = wm.keyconfigs.addon
- if kc:
- km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
- kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
- kmi.properties.total = 4
- addon_keymaps.append((km, kmi))
-
- def unregister():
- # Note: when unregistering, it's usually good practice to do it in reverse order you registered.
- # Can avoid strange issues like keymap still referring to operators already unregistered...
- # handle the keymap
- for km, kmi in addon_keymaps:
- km.keymap_items.remove(kmi)
- addon_keymaps.clear()
-
- bpy.utils.unregister_class(ObjectCursorArray)
- bpy.types.VIEW3D_MT_object.remove(menu_func)
-
-
- if __name__ == "__main__":
- register()
-
-.. image:: in_menu.png
- :width: 591px
- :align: center
- :height: 649px
- :alt: In the menu
-
-Run the script (or save it and add it through the Preferences like before) and it will appear in the menu.
-
-.. image:: op_prop.png
- :width: 669px
- :align: center
- :height: 644px
- :alt: Operator Property
-
-After selecting it from the menu, you can choose how many instance of the cube you want created.
-
-
-.. note::
-
- Directly executing the script multiple times will add the menu each time too.
- While not useful behavior, theres nothing to worry about since add-ons won't register them selves multiple
- times when enabled through the user preferences.
-
-
-Conclusions
-===========
-
-Add-ons can encapsulate certain functionality neatly for writing tools to improve your work-flow or for writing utilities
-for others to use.
-
-While there are limits to what Python can do within Blender, there is certainly a lot that can be achieved without
-having to dive into Blender's C/C++ code.
-
-The example given in the tutorial is limited, but shows the Blender API used for common tasks that you can expand on
-to write your own tools.
-
-
-Further Reading
----------------
-
-Blender comes commented templates which are accessible from the text editor header, if you have specific areas
-you want to see example code for, this is a good place to start.
-
-
-Here are some sites you might like to check on after completing this tutorial.
-
-- :ref:`Blender/Python API Overview <info_overview>` -
- *For more background details on Blender/Python integration.*
-- `How to Think Like a Computer Scientist <http://interactivepython.org/courselib/static/thinkcspy/index.html>`_ -
- *Great info for those who are still learning Python.*
-- `Blender Development (Wiki) <https://wiki.blender.org/index.php/Dev:Contents>`_ -
- *Blender Development, general information and helpful links.*
-- `Blender Artists (Coding Section) <https://blenderartists.org/forum/forumdisplay.php?47-Coding>`_ -
- *forum where people ask Python development questions*
-
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index 241929c24d9..61dbb92938a 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -362,8 +362,6 @@ INFO_DOCS = (
"Blender/Python Quickstart: new to Blender/scripting and want to get your feet wet?"),
("info_overview.rst",
"Blender/Python API Overview: a more complete explanation of Python integration"),
- ("info_tutorial_addon.rst",
- "Blender/Python Add-on Tutorial: a step by step guide on how to write an add-on from scratch"),
("info_api_reference.rst",
"Blender/Python API Reference Usage: examples of how to use the API reference docs"),
("info_best_practice.rst",
@@ -1699,6 +1697,9 @@ def write_rst_contents(basepath):
for info, info_desc in INFO_DOCS:
fw(" %s <%s>\n\n" % (info_desc, info))
fw("\n")
+ fw("- :ref:`Blender/Python Add-on Tutorial: a step by step guide on")
+ fw(" how to write an add-on from scratch <blender_manual:advanced_scripting_tutorial>`\n")
+ fw("\n")
fw(title_string("Application Modules", "=", double=True))
fw(".. toctree::\n")