diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/doxygen/Doxyfile | 2 | ||||
-rw-r--r-- | doc/python_api/examples/bpy.app.translations.py | 59 | ||||
-rw-r--r-- | doc/python_api/examples/bpy.types.Operator.5.py | 15 | ||||
-rw-r--r-- | doc/python_api/rst/bge.app.rst | 1 | ||||
-rw-r--r-- | doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst | 4 | ||||
-rw-r--r-- | doc/python_api/rst/gpu.rst | 8 | ||||
-rw-r--r-- | doc/python_api/rst/include__bmesh.rst | 15 | ||||
-rw-r--r-- | doc/python_api/rst/info_overview.rst | 44 | ||||
-rw-r--r-- | doc/python_api/rst/info_tutorial_addon.rst | 635 | ||||
-rw-r--r-- | doc/python_api/rst_from_bmesh_opdefines.py | 2 | ||||
-rw-r--r-- | doc/python_api/sphinx_doc_gen.py | 60 | ||||
-rw-r--r-- | doc/python_api/static/blender_logo.svg | 116 | ||||
-rw-r--r-- | doc/python_api/static/favicon.ico (renamed from doc/python_api/blender-org/static/favicon.ico) | bin | 1150 -> 1150 bytes |
13 files changed, 261 insertions, 700 deletions
diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 8b3a97816ba..a3ccf9227d3 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = Blender # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "V2.8x" +PROJECT_NUMBER = "V2.79" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/doc/python_api/examples/bpy.app.translations.py b/doc/python_api/examples/bpy.app.translations.py index e41623d2885..4256147ef31 100644 --- a/doc/python_api/examples/bpy.app.translations.py +++ b/doc/python_api/examples/bpy.app.translations.py @@ -32,3 +32,62 @@ Module References ----------------- """ + +import bpy + +# This block can be automatically generated by UI translations addon, which also handles conversion with PO format. +# See also https://wiki.blender.org/index.php/Dev:Doc/Process/Translate_Blender#Translating_non-official_addons +# It can (should) also be put in a different, specific py file. + +# ##### BEGIN AUTOGENERATED I18N SECTION ##### +# NOTE: You can safely move around this auto-generated block (with the begin/end markers!), +# and edit the translations by hand. +# Just carefully respect the format of the tuple! + +# Tuple of tuples ((msgctxt, msgid), (sources, gen_comments), (lang, translation, (is_fuzzy, comments)), ...) +translations_tuple = ( + (("*", ""), + ((), ()), + ("fr_FR", "Project-Id-Version: Copy Settings 0.1.5 (r0)\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2013-04-18 15:27:45.563524\nPO-Revision-Date: 2013-04-18 15:38+0100\nLast-Translator: Bastien Montagne <montagne29@wanadoo.fr>\nLanguage-Team: LANGUAGE <LL@li.org>\nLanguage: __POT__\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\n", + (False, + ("Blender's translation file (po format).", + "Copyright (C) 2013 The Blender Foundation.", + "This file is distributed under the same license as the Blender package.", + "FIRST AUTHOR <EMAIL@ADDRESS>, YEAR."))), + ), + (("Operator", "Render: Copy Settings"), + (("bpy.types.SCENE_OT_render_copy_settings",), + ()), + ("fr_FR", "Rendu : copier réglages", + (False, ())), + ), + (("*", "Copy render settings from current scene to others"), + (("bpy.types.SCENE_OT_render_copy_settings",), + ()), + ("fr_FR", "Copier les réglages de rendu depuis la scène courante vers d’autres", + (False, ())), + ), + # ... etc, all messages from your addon. +) + +translations_dict = {} +for msg in translations_tuple: + key = msg[0] + for lang, trans, (is_fuzzy, comments) in msg[2:]: + if trans and not is_fuzzy: + translations_dict.setdefault(lang, {})[key] = trans + +# ##### END AUTOGENERATED I18N SECTION ##### + +# Define remaining addon (operators, UI...) here. + +def register(): + # Usual operator/UI/etc. registration... + + bpy.app.translations.register(__name__, translations_dict) + + +def unregister(): + bpy.app.translations.unregister(__name__) + + # Usual operator/UI/etc. unregistration... diff --git a/doc/python_api/examples/bpy.types.Operator.5.py b/doc/python_api/examples/bpy.types.Operator.5.py index 310eeceadf3..c1a49a756a0 100644 --- a/doc/python_api/examples/bpy.types.Operator.5.py +++ b/doc/python_api/examples/bpy.types.Operator.5.py @@ -2,13 +2,14 @@ Modal Execution +++++++++++++++ -This operator defines a :class:`Operator.modal` function which running, -handling events until it returns ``{'FINISHED'}`` or ``{'CANCELLED'}``. - -Grab, Rotate, Scale and Fly-Mode are examples of modal operators. -They are especially useful for interactive tools, -your operator can have its own state where keys toggle options as the operator -runs. +This operator defines a :class:`Operator.modal` function that will keep being +run to handle events until it returns ``{'FINISHED'}`` or ``{'CANCELLED'}``. + +Modal operators run every time a new event is detected, such as a mouse click +or key press. Conversely, when no new events are detected, the modal operator +will not run. Modal operators are especially useful for interactive tools, an +operator can have its own state where keys toggle options as the operator runs. +Grab, Rotate, Scale, and Fly-Mode are examples of modal operators. :class:`Operator.invoke` is used to initialize the operator as being by returning ``{'RUNNING_MODAL'}``, initializing the modal loop. diff --git a/doc/python_api/rst/bge.app.rst b/doc/python_api/rst/bge.app.rst index 34b9263db0c..e8b91ffbcaf 100644 --- a/doc/python_api/rst/bge.app.rst +++ b/doc/python_api/rst/bge.app.rst @@ -47,4 +47,3 @@ Module to access application values that remain unchanged during runtime. True if the BGE has been built with physics support. :type: bool - diff --git a/doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst b/doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst index d08a761ed95..4bb3d273cb9 100644 --- a/doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst +++ b/doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst @@ -59,7 +59,7 @@ base class --- :class:`SCA_IActuator` .. attribute:: mode - The operation mode of the actuator. Can be one of :ref:`these constants<shape-action-actuator>`. + The operation mode of the actuator. Can be one of :ref:`these constants<action-actuator>`. :type: integer @@ -68,5 +68,3 @@ base class --- :class:`SCA_IActuator` The name of the property that is set to the current frame number. :type: string - - diff --git a/doc/python_api/rst/gpu.rst b/doc/python_api/rst/gpu.rst index 6c38122a573..cf639357a31 100644 --- a/doc/python_api/rst/gpu.rst +++ b/doc/python_api/rst/gpu.rst @@ -6,6 +6,13 @@ GPU functions (gpu) This module provides access to materials GLSL shaders. +Submodules: + +.. toctree:: + :maxdepth: 1 + + gpu.offscreen.rst + Intro ===== @@ -24,7 +31,6 @@ and in the game engine. Constants ========= - GLSL Data Type -------------- diff --git a/doc/python_api/rst/include__bmesh.rst b/doc/python_api/rst/include__bmesh.rst index 83e3e73cea4..bed374bf7b6 100644 --- a/doc/python_api/rst/include__bmesh.rst +++ b/doc/python_api/rst/include__bmesh.rst @@ -7,14 +7,17 @@ Submodules: -* :mod:`bmesh.ops` -* :mod:`bmesh.types` -* :mod:`bmesh.utils` -* :mod:`bmesh.geometry` +.. toctree:: + :maxdepth: 1 + bmesh.ops.rst + bmesh.types.rst + bmesh.utils.rst + bmesh.geometry.rst -Intro ------ + +Introduction +------------ This API gives access the blenders internal mesh editing api, featuring geometry connectivity data and access to editing operations such as split, separate, collapse and dissolve. diff --git a/doc/python_api/rst/info_overview.rst b/doc/python_api/rst/info_overview.rst index ba2e6949b81..721374cd472 100644 --- a/doc/python_api/rst/info_overview.rst +++ b/doc/python_api/rst/info_overview.rst @@ -5,23 +5,25 @@ Python API Overview ******************* -This document is to give an understanding of how Python and Blender fit together, -covering some of the functionality that isn't obvious from reading the API reference and example scripts. +The purpose of this document is to explain how Python and Blender fit together, +covering some of the functionality that may not be obvious from reading the API +references and example scripts. Python in Blender ================= -Blender embeds a Python interpreter which is started with Blender and stays active. -This interpreter runs scripts to draw the user interface and is used for some of Blender's internal tools too. +Blender has an embedded Python interpreter which is loaded when Blender is started and stays +active while Blender is running. This interpreter runs scripts to draw the user interface +and is used for some of Blender’s internal tools as well. -This is a typical Python environment so tutorials on how to write Python scripts -will work running the scripts in Blender too. -Blender provides the :mod:`bpy` module to the Python interpreter. -This module can be imported in a script and gives access to Blender data, classes, and functions. -Scripts that deal with Blender data will need to import this module. +Blender's embedded interpreter provides a typical Python environment, so code from tutorials +on how to write Python scripts can also be run with Blender’s interpreter. Blender provides its +Python modules, such as :mod:`bpy` and :mod:`mathutils`, to the embedded interpreter so they can +be imported into a script and give access to Blender's data, classes, and functions. Scripts that +deal with Blender data will need to import the modules to work. -Here is a simple example of moving a vertex of the object named **Cube**: +Here is a simple example which moves a vertex attached to an object named **Cube**: .. code-block:: python @@ -49,15 +51,17 @@ See the :ref:`directory layout docs <blender_manual:getting-started_installing-c Script Loading ============== -This may seem obvious but it's important to note the difference -between executing a script directly or importing it as a module. +This may seem obvious, but it is important to note the difference between +executing a script directly and importing a script as a module. -Scripts that extend Blender - define classes that exist beyond the scripts execution, -this makes future access to these classes (to unregister for example) -more difficult than importing as a module where class instance is kept -in the module and can be accessed by importing that module later on. +Extending Blender by executing a script directly means the classes that the script +defines remain available inside Blender after the script finishes execution. +Using scripts this way makes future access to their classes +(to unregister them for example) more difficult compared to importing the scripts as modules. +When a script is imported as a module, its class instances will remain +inside the module and can be accessed later on by importing that module again. -For this reason it's preferable to only use directly execute scripts that don't extend Blender by registering classes. +For this reason it is preferable to avoid directly executing scripts that extend Blender by registering classes. Here are some ways to run scripts directly in Blender. @@ -396,8 +400,8 @@ This works just as well for PropertyGroup subclasses you define yourself. Dynamic Defined-Classes (Advanced) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -In some cases the specifier for data may not be in Blender, -renderman shader definitions for example and it may be useful to define types and remove them on the fly. +In some cases the specifier for data may not be in Blender, renderman shader definitions +for example, and it may be useful to define them as types and remove them on the fly. .. code-block:: python @@ -420,7 +424,7 @@ renderman shader definitions for example and it may be useful to define types an This is an alternative syntax for class creation in Python, better suited to constructing classes dynamically. -Calling these operators: +To call the operators from the previous example: >>> bpy.ops.object.operator_1() Hello World OBJECT_OT_operator_1 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/rst_from_bmesh_opdefines.py b/doc/python_api/rst_from_bmesh_opdefines.py index cdbed88cc88..d3e4b2a0cfd 100644 --- a/doc/python_api/rst_from_bmesh_opdefines.py +++ b/doc/python_api/rst_from_bmesh_opdefines.py @@ -22,7 +22,7 @@ # 'bmesh_opdefines.c' in order to avoid having to add a lot of introspection # data access into the api. # -# The script is stupid becase it makes assumptions about formatting... +# The script is stupid because it makes assumptions about formatting... # that each arg has its own line, that comments above or directly after will be __doc__ etc... # # We may want to replace this script with something else one day but for now its good enough. diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 47bb323e574..08c3e729ed9 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -341,6 +341,8 @@ EXTRA_SOURCE_FILES = ( "../examples/bge.texture.py", "../examples/bmesh.ops.1.py", "../examples/bpy.app.translations.py", + "../static/favicon.ico", + "../static/blender_logo.svg", ) @@ -362,8 +364,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", @@ -1010,9 +1010,9 @@ def pymodule2sphinx(basepath, module_name, module, title): context_type_map = { "active_base": ("ObjectBase", False), "active_bone": ("EditBone", False), + "active_gpencil_brush": ("GPencilSculptBrush", False), "active_gpencil_frame": ("GreasePencilLayer", True), "active_gpencil_layer": ("GPencilLayer", True), - "active_gpencil_brush": ("GPencilSculptBrush", False), "active_gpencil_palette": ("GPencilPalette", True), "active_gpencil_palettecolor": ("GPencilPaletteColor", True), "active_node": ("Node", False), @@ -1063,6 +1063,7 @@ context_type_map = { "selected_bones": ("EditBone", True), "selected_editable_bases": ("ObjectBase", True), "selected_editable_bones": ("EditBone", True), + "selected_editable_fcurves": ("FCurce", True), "selected_editable_objects": ("Object", True), "selected_editable_sequences": ("Sequence", True), "selected_nodes": ("Node", True), @@ -1613,10 +1614,8 @@ def pyrna2sphinx(basepath): else: url_base = API_BASEURL - fw(" :file: `%s <%s/%s>`_:%d\n\n" % (location[0], - url_base, - location[0], - location[1])) + fw(" :file: `%s\\:%d <%s/%s$%d>`_\n\n" % + (location[0], location[1], url_base, location[0], location[1])) file.close() @@ -1641,19 +1640,24 @@ def write_sphinx_conf_py(basepath): fw("version = '%s - API'\n" % BLENDER_VERSION_DOTS) fw("release = '%s - API'\n" % BLENDER_VERSION_DOTS) + # Quiet file not in table-of-contents warnings. + fw("exclude_patterns = [\n") + fw(" 'include__bmesh.rst',\n") + fw("]\n\n") + if ARGS.sphinx_theme != 'default': fw("html_theme = '%s'\n" % ARGS.sphinx_theme) if ARGS.sphinx_theme == "blender-org": fw("html_theme_path = ['../']\n") - # copied with the theme, exclude else we get an error [T28873] - fw("html_favicon = 'favicon.ico'\n") # in <theme>/static/ # not helpful since the source is generated, adds to upload size. fw("html_copy_source = False\n") fw("html_show_sphinx = False\n") fw("html_split_index = True\n") - fw("\n") + fw("html_extra_path = ['__/static/favicon.ico', '__/static/blender_logo.svg']\n") + fw("html_favicon = '__/static/favicon.ico'\n") + fw("html_logo = '__/static/blender_logo.svg'\n\n") # needed for latex, pdf gen fw("latex_elements = {\n") @@ -1661,6 +1665,24 @@ def write_sphinx_conf_py(basepath): fw("}\n\n") fw("latex_documents = [ ('contents', 'contents.tex', 'Blender Index', 'Blender Foundation', 'manual'), ]\n") + + # Workaround for useless links leading to compile errors + # See https://github.com/sphinx-doc/sphinx/issues/3866 + fw(r""" +from sphinx.domains.python import PythonDomain + +class PatchedPythonDomain(PythonDomain): + def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode): + if 'refspecific' in node: + del node['refspecific'] + return super(PatchedPythonDomain, self).resolve_xref( + env, fromdocname, builder, typ, target, node, contnode) + +def setup(sphinx): + sphinx.override_domain(PatchedPythonDomain) +""") + # end workaround + file.close() @@ -1715,8 +1737,6 @@ def write_rst_contents(basepath): "bpy.utils.previews", "bpy.path", "bpy.app", - "bpy.app.handlers", - "bpy.app.translations", # C modules "bpy.props", @@ -1731,19 +1751,9 @@ def write_rst_contents(basepath): fw(" :maxdepth: 1\n\n") standalone_modules = ( - # mathutils - "mathutils", - "mathutils.geometry", - "mathutils.bvhtree", "mathutils.kdtree", - "mathutils.interpolate", - "mathutils.noise", - # misc - "freestyle", "bgl", "blf", - "gpu", "gpu.offscreen", - "aud", "bpy_extras", - "idprop.types", - # bmesh, submodules are in own page - "bmesh", + # submodules are added in parent page + "mathutils", "freestyle", "bgl", "blf", "gpu", + "aud", "bpy_extras", "idprop.types", "bmesh", ) for mod in standalone_modules: diff --git a/doc/python_api/static/blender_logo.svg b/doc/python_api/static/blender_logo.svg new file mode 100644 index 00000000000..bbf446c9bec --- /dev/null +++ b/doc/python_api/static/blender_logo.svg @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + id="svg8" + version="1.1" + viewBox="0 0 55.032989 15.935012" + height="60.226818" + width="207.9987"> + <defs + id="defs2"> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3020"> + <path + style="stroke-width:1.06666672" + d="M 0,0 H 211.2 V 61.866667 H 0 Z" + id="path3022" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3020-8"> + <path + style="stroke-width:1.06666672" + d="M 0,0 H 211.2 V 61.866667 H 0 Z" + id="path3022-1" /> + </clipPath> + </defs> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:creator> + <cc:Agent> + <dc:title>Blender Logo</dc:title> + </cc:Agent> + </dc:creator> + <dc:source>https://www.blender.org/about/logo/</dc:source> + <cc:license + rdf:resource="(c) Blender Foundation" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + transform="translate(42.023693,-77.734934)" + id="layer1"> + <g + transform="matrix(0.26259939,0,0,-0.26259939,-42.237694,93.888967)" + id="g3012" + style="stroke-width:7.2904439"> + <g + id="g3014" + style="stroke-width:7.2904439" /> + <g + id="g3016" + style="stroke-width:7.2904439"> + <g + clip-path="url(#clipPath3020-8)" + id="g3018" + style="stroke-width:7.2904439"> + <path + id="path3024" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352" + d="m 192.54827,44.510933 c 0,0 -125.158403,0 -128.688003,0 -0.07893,0.06187 -0.1504,0.1344 -0.2272,0.193067 -0.01813,0.0192 -18.9312,14.548267 -19.5008,14.986667 -0.032,0.0256 -0.06507,0.04907 -0.06507,0.04907 -3.029333,2.321067 -7.531733,2.369067 -10.721067,0.133334 -1.9968,-1.396267 -3.194666,-3.508267 -3.285333,-5.792 -0.0021,-0.09173 -0.0064,-0.1824 -0.0064,-0.2752 0,-1.185067 0.314667,-2.3296 0.8832,-3.357867 -5.857067,-0.0053 -11.746133,-0.0128 -11.746133,-0.0128 -4.3936,-0.0021 -8.3648,-2.965333 -9.2725337,-6.8928 C 9.7898667,42.9792 9.7248,42.411733 9.7248,41.8496 c 0,-1.643733 0.546133,-3.236267 1.5808,-4.542933 1.162667,-1.463467 2.842667,-2.448 4.7584,-2.832 C 10.530133,30.2272 5.0016,25.984 4.9973333,25.979733 4.9578667,25.949867 4.9248,25.924267 4.8970667,25.905067 c -2.2176,-1.703467 -3.68,-4.1728 -4.0106667,-6.770134 -0.0490667,-0.381866 -0.0714667,-0.7584 -0.0714667,-1.133866 0,-1.870934 0.5962667,-3.650134 1.7301334,-5.102934 1.3781333,-1.764266 3.4144,-2.884266 5.7322666,-3.147733 2.6549337,-0.3072 5.4495997,0.542933 7.6607997,2.330667 0.01493,0.01173 2.753067,2.256 5.639467,4.6176 1.060267,-2.555734 2.545067,-4.926934 4.465067,-7.0453337 2.4704,-2.7306666 5.473066,-4.8864 8.919466,-6.4128 C 38.5856,1.6352 42.466133,0.82453333 46.501333,0.83413333 50.5376,0.8416 54.417067,1.6629333 58.0352,3.2768 c 3.453867,1.5466667 6.449067,3.7109333 8.910933,6.4352 0.360534,0.4032 0.693334,0.8288 1.0272,1.2544 4.885334,0 124.574937,0 124.574937,0 9.84,0 17.8368,7.5232 17.8368,16.7712 0,9.248 -7.9968,16.773333 -17.8368,16.773333" /> + <path + id="path3026" + style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352" + d="m 38.538667,28.497067 c 0.113066,2.016 1.101866,3.793066 2.590933,5.0528 1.4624,1.237333 3.428267,1.9936 5.575467,1.9936 2.144,0 4.110933,-0.756267 5.572266,-1.9936 1.490134,-1.259734 2.4768,-3.0368 2.590934,-5.050667 0.113066,-2.0736 -0.718934,-3.997867 -2.181334,-5.425067 C 51.1968,21.6224 49.0784,20.7104 46.705067,20.7104 c -2.3744,0 -4.497067,0.912 -5.9872,2.363733 -1.461334,1.4272 -2.292267,3.351467 -2.1792,5.422934" /> + <path + id="path3028" + style="fill:#f5792a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352" + d="m 25.536,24.421333 c 0.01387,-0.7904 0.2656,-2.3232 0.6432,-3.521066 C 26.9728,18.3648 28.318933,16.0192 30.193067,13.950933 32.1152,11.8272 34.482133,10.119467 37.216,8.9088 c 2.872533,-1.2736 5.986133,-1.9210667 9.220267,-1.9157333 3.229866,0.00427 6.3424,0.6656 9.216,1.9477333 2.733866,1.2224 5.098666,2.9376 7.018666,5.063467 1.870934,2.074666 3.216,4.424533 4.010667,6.96 0.401067,1.282133 0.6528,2.581333 0.754133,3.886933 0.100267,1.285333 0.0576,2.571733 -0.1248,3.858133 -0.356266,2.507734 -1.223466,4.858667 -2.557866,7.002667 -1.2224,1.970133 -2.7968,3.696 -4.6688,5.147733 l 0.0053,0.0021 -18.8928,14.506666 c -0.016,0.0128 -0.02987,0.02667 -0.048,0.03733 -1.240533,0.952533 -3.3248,0.948266 -4.686933,-0.0053 -1.3792,-0.9632 -1.536,-2.557866 -0.3104,-3.5648 l -0.0043,-0.0043 7.8784,-6.407467 -24.016,-0.02667 c -0.01173,0 -0.0224,0 -0.032,0 -1.985067,-0.0011 -3.893333,-1.303466 -4.269867,-2.9504 -0.389333,-1.6768 0.958934,-3.067733 3.022934,-3.074133 l -0.0021,-0.0075 L 30.900267,39.3888 9.1786667,22.715733 c -0.026667,-0.02133 -0.0576,-0.0416 -0.0832,-0.06293 -2.0490667,-1.568 -2.7104,-4.178133 -1.4197334,-5.828267 1.3088,-1.68 4.0949337,-1.6832 6.1653337,-0.0096 L 25.696,26.516267 c 0,0 -0.173867,-1.3088 -0.16,-2.094934 z M 56,20.034133 c -2.443733,-2.488533 -5.8624,-3.899733 -9.563733,-3.9072 -3.7056,-0.0064 -7.124267,1.393067 -9.568,3.877334 -1.1936,1.210666 -2.0704,2.602666 -2.6112,4.087466 -0.529067,1.457067 -0.736,3.0048 -0.599467,4.5664 0.130133,1.527467 0.583467,2.9824 1.309867,4.3008 0.712533,1.293867 1.6928,2.465067 2.9056,3.454934 2.373333,1.934933 5.396266,2.981333 8.558933,2.9856 3.1648,0.0053 6.1856,-1.0336 8.561067,-2.961067 1.2096,-0.9856 2.190933,-2.151467 2.903466,-3.445333 0.728534,-1.316267 1.179734,-2.765867 1.314134,-4.2976 C 59.344,27.136 59.138133,25.5904 58.609067,24.1312 58.0672,22.6432 57.1936,21.2512 56,20.034133" /> + <path + id="path3030" + style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352" + d="m 167.96587,28.529067 c 0.1824,2.0352 1.75466,3.325866 4.15786,3.325866 2.4064,0 3.97974,-1.290666 4.16214,-3.325866 z M 176.0384,23.504 c -0.61547,-1.508267 -2.06507,-2.401067 -4.03627,-2.401067 -2.46613,0 -4.12693,1.540267 -4.1952,3.9744 h 14.18347 c 0,0.251734 0,0.462934 0,0.715734 0,6.094933 -3.57653,9.518933 -9.98827,9.518933 -6.22506,0 -9.98826,-3.457067 -9.98826,-8.878933 0,-5.454934 3.82293,-8.9056 9.98826,-8.9056 3.70134,0 6.5696,1.2672 8.33814,3.4976 L 176.0384,23.504" /> + <path + id="path3032" + style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352" + d="m 105.0336,28.519467 c 0.18667,2.036266 1.76,3.326933 4.16533,3.326933 2.40214,0 3.97547,-1.290667 4.15894,-3.326933 z m 8.07787,-5.025067 c -0.61547,-1.512533 -2.06614,-2.404267 -4.03947,-2.404267 -2.464,0 -4.12907,1.544534 -4.19413,3.9776 h 14.18026 c 0,0.2496 0,0.4608 0,0.712534 0,6.098133 -3.57546,9.524266 -9.98613,9.524266 -6.22933,0 -9.986133,-3.458133 -9.986133,-8.88 0,-5.456 3.821863,-8.906666 9.986133,-8.906666 3.6992,0 6.5696,1.262933 8.34133,3.495466 l -4.30186,2.481067" /> + <path + id="path3034" + style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352" + d="m 92.701867,38.997333 h 5.114666 v -20.9248 h -5.114666 z" /> + <path + id="path3036" + style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352" + d="m 120.33067,33.438933 h 5.14453 v -1.245866 c 1.8208,1.9424 4.00747,2.9248 6.47253,2.9248 2.84054,0 4.992,-0.9824 6.1024,-2.653867 0.92587,-1.381333 0.98774,-3.0496 0.98774,-5.239467 v -9.152 h -5.15094 v 8.040534 c 0,3.336533 -0.67093,4.877866 -3.6,4.877866 -2.96106,0 -4.81173,-1.764266 -4.81173,-4.724266 v -8.194134 h -5.14453 v 15.3664" /> + <path + id="path3038" + style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352" + d="m 155.60107,26.173867 c 0,-2.864 -1.9136,-4.741334 -4.8736,-4.741334 -2.96427,0 -4.87787,1.813334 -4.87787,4.709334 0,2.9376 1.88907,4.750933 4.87787,4.750933 2.96,0 4.8736,-1.8464 4.8736,-4.718933 z m 0,6.568533 c -1.30027,1.393067 -3.1808,2.157867 -5.79734,2.157867 -5.64266,0 -9.49546,-3.479467 -9.49546,-8.6944 0,-5.112534 3.82613,-8.688 9.40266,-8.688 2.5568,0 4.4352,0.645333 5.89014,2.096 v -1.541334 h 5.14666 v 22.2528 l -5.14666,-1.328 V 32.7424" /> + <path + id="path3040" + style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352" + d="m 81.010133,30.8928 c 2.990934,0 4.871467,-1.813333 4.871467,-4.750933 0,-2.896 -1.9104,-4.709334 -4.871467,-4.709334 -2.958933,0 -4.869333,1.877334 -4.869333,4.741334 0,2.872533 1.9104,4.718933 4.869333,4.718933 z m -4.869333,8.104533 -5.1488,1.328 v -22.2528 h 5.1488 v 1.541334 c 1.448533,-1.450667 3.329067,-2.096 5.886933,-2.096 5.579734,0 9.4016,3.575466 9.4016,8.688 0,5.214933 -3.853866,8.6944 -9.493333,8.6944 -2.621867,0 -4.5024,-0.7648 -5.7952,-2.157867 v 6.254933" /> + <path + id="path3042" + style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352" + d="m 183.2608,18.072533 v 15.3664 h 5.14667 v -0.9504 c 1.54026,1.857067 3.1712,2.7808 5.0272,2.7808 0.368,0 0.82986,-0.05973 1.44533,-0.1216 V 30.768 c -0.496,0.064 -1.04747,0.064 -1.6352,0.064 -2.992,0 -4.83733,-1.972267 -4.83733,-5.329067 v -7.4304 h -5.14667" /> + <path + id="path3044" + style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352" + d="m 201.55307,35.252267 h -0.39467 l 0.0139,1.409066 0.0203,0.466134 -0.1056,-0.384 -0.46826,-1.4912 h -0.36054 l -0.45866,1.4912 -0.1152,0.376533 0.0277,-0.458667 0.0139,-1.409066 h -0.38614 v 2.282666 h 0.54187 l 0.57067,-1.8016 0.5568,1.8016 h 0.544 z m -3.12747,0 h -0.39787 V 37.1968 h -0.7328 v 0.338133 h 1.85067 V 37.1968 h -0.72 v -1.944533" /> + </g> + </g> + </g> + </g> +</svg> diff --git a/doc/python_api/blender-org/static/favicon.ico b/doc/python_api/static/favicon.ico Binary files differindex f125d24dcb6..f125d24dcb6 100644 --- a/doc/python_api/blender-org/static/favicon.ico +++ b/doc/python_api/static/favicon.ico |