diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/doxygen/Doxyfile | 2 | ||||
-rwxr-xr-x | doc/manpage/blender.1.py | 2 | ||||
-rw-r--r-- | doc/python_api/examples/gpu.1.py | 1 | ||||
-rw-r--r-- | doc/python_api/examples/gpu.10.py | 1 | ||||
-rw-r--r-- | doc/python_api/examples/gpu.2.py | 1 | ||||
-rw-r--r-- | doc/python_api/examples/gpu.3.py | 1 | ||||
-rw-r--r-- | doc/python_api/examples/gpu.5.py | 1 | ||||
-rw-r--r-- | doc/python_api/examples/gpu.6.py | 1 | ||||
-rw-r--r-- | doc/python_api/examples/gpu.7.py | 1 | ||||
-rw-r--r-- | doc/python_api/requirements.txt | 10 | ||||
-rw-r--r-- | doc/python_api/rst/change_log.rst | 6 | ||||
-rw-r--r-- | doc/python_api/rst/info_advanced.rst | 15 | ||||
-rw-r--r-- | doc/python_api/rst/info_advanced_blender_as_bpy.rst | 126 | ||||
-rw-r--r-- | doc/python_api/rst/info_api_reference.rst | 2 | ||||
-rw-r--r-- | doc/python_api/rst/info_overview.rst | 6 | ||||
-rw-r--r-- | doc/python_api/rst_from_bmesh_opdefines.py | 22 | ||||
-rw-r--r-- | doc/python_api/sphinx_changelog_gen.py | 22 | ||||
-rw-r--r-- | doc/python_api/sphinx_doc_gen.py | 53 |
18 files changed, 219 insertions, 54 deletions
diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 18c16a60993..e1d8ac39bcf 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 = V3.4 +PROJECT_NUMBER = V3.5 # 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/manpage/blender.1.py b/doc/manpage/blender.1.py index 7d35dc0abb1..49dae35e0c5 100755 --- a/doc/manpage/blender.1.py +++ b/doc/manpage/blender.1.py @@ -139,7 +139,7 @@ https://www.blender.org''') l = lines.pop(0) if l: - assert(l.startswith('\t')) + assert l.startswith('\t') l = l[1:] # Remove first white-space (tab). fh.write('%s\n' % man_format(l)) diff --git a/doc/python_api/examples/gpu.1.py b/doc/python_api/examples/gpu.1.py index a014e69c2d2..c44e79a77aa 100644 --- a/doc/python_api/examples/gpu.1.py +++ b/doc/python_api/examples/gpu.1.py @@ -134,7 +134,6 @@ batch = batch_for_shader(shader, 'LINES', {"pos": coords}) def draw(): - shader.bind() shader.uniform_float("color", (1, 1, 0, 1)) batch.draw(shader) diff --git a/doc/python_api/examples/gpu.10.py b/doc/python_api/examples/gpu.10.py index b47ff732e2b..6c438bd396e 100644 --- a/doc/python_api/examples/gpu.10.py +++ b/doc/python_api/examples/gpu.10.py @@ -58,7 +58,6 @@ batch = batch_for_shader( def draw(): - shader.bind() matrix = bpy.context.region_data.perspective_matrix shader.uniform_float("u_ViewProjectionMatrix", matrix) shader.uniform_float("u_Scale", 10) diff --git a/doc/python_api/examples/gpu.2.py b/doc/python_api/examples/gpu.2.py index 2a46e833752..e308ce7f78e 100644 --- a/doc/python_api/examples/gpu.2.py +++ b/doc/python_api/examples/gpu.2.py @@ -41,7 +41,6 @@ batch = batch_for_shader(shader, 'TRIS', {"position": coords}) def draw(): - shader.bind() matrix = bpy.context.region_data.perspective_matrix shader.uniform_float("viewProjectionMatrix", matrix) shader.uniform_float("brightness", 0.5) diff --git a/doc/python_api/examples/gpu.3.py b/doc/python_api/examples/gpu.3.py index 0c86b52bcf5..9e8f762d9c9 100644 --- a/doc/python_api/examples/gpu.3.py +++ b/doc/python_api/examples/gpu.3.py @@ -22,7 +22,6 @@ batch = batch_for_shader(shader, 'LINES', {"pos": coords}, indices=indices) def draw(): - shader.bind() shader.uniform_float("color", (1, 0, 0, 1)) batch.draw(shader) diff --git a/doc/python_api/examples/gpu.5.py b/doc/python_api/examples/gpu.5.py index 2edde46a364..983372706c1 100644 --- a/doc/python_api/examples/gpu.5.py +++ b/doc/python_api/examples/gpu.5.py @@ -18,7 +18,6 @@ batch = batch_for_shader(shader, 'TRIS', {"pos": vertices}, indices=indices) def draw(): - shader.bind() shader.uniform_float("color", (0, 0.5, 0.5, 1.0)) batch.draw(shader) diff --git a/doc/python_api/examples/gpu.6.py b/doc/python_api/examples/gpu.6.py index 5576b2d0bfe..96decf571ee 100644 --- a/doc/python_api/examples/gpu.6.py +++ b/doc/python_api/examples/gpu.6.py @@ -56,7 +56,6 @@ batch = batch_for_shader( def draw(): - shader.bind() shader.uniform_sampler("image", texture) batch.draw(shader) diff --git a/doc/python_api/examples/gpu.7.py b/doc/python_api/examples/gpu.7.py index e3bfbd14e34..5d25b42728d 100644 --- a/doc/python_api/examples/gpu.7.py +++ b/doc/python_api/examples/gpu.7.py @@ -76,7 +76,6 @@ batch = batch_for_shader( def draw(): - shader.bind() shader.uniform_float("modelMatrix", Matrix.Translation((1, 2, 3)) @ Matrix.Scale(3, 4)) shader.uniform_float("viewProjectionMatrix", bpy.context.region_data.perspective_matrix) shader.uniform_sampler("image", offscreen.texture_color) diff --git a/doc/python_api/requirements.txt b/doc/python_api/requirements.txt index f93947c9d2d..4b31c3f1344 100644 --- a/doc/python_api/requirements.txt +++ b/doc/python_api/requirements.txt @@ -1,13 +1,13 @@ -sphinx==5.0.1 +sphinx==5.3.0 # Sphinx dependencies that are important Jinja2==3.1.2 -Pygments==2.12.0 +Pygments==2.13.0 docutils==0.17.1 snowballstemmer==2.2.0 -babel==2.10.1 -requests==2.27.1 +babel==2.11.0 +requests==2.28.1 # Only needed to match the theme used for the official documentation. # Without this theme, the default theme will be used. -sphinx_rtd_theme==1.0.0 +sphinx_rtd_theme==1.1.0 diff --git a/doc/python_api/rst/change_log.rst b/doc/python_api/rst/change_log.rst index 957bf8605e3..ef289cd0762 100644 --- a/doc/python_api/rst/change_log.rst +++ b/doc/python_api/rst/change_log.rst @@ -1,7 +1,9 @@ :tocdepth: 2 -Blender API Change Log -********************** +Change Log +********** + +Changes in Blender's Python API between releases. .. note, this document is auto generated by sphinx_changelog_gen.py diff --git a/doc/python_api/rst/info_advanced.rst b/doc/python_api/rst/info_advanced.rst new file mode 100644 index 00000000000..cae1e711722 --- /dev/null +++ b/doc/python_api/rst/info_advanced.rst @@ -0,0 +1,15 @@ +.. _info_advanced-index: + +******** +Advanced +******** + +This chapter covers advanced use (topics which may not be required for typical usage). + +.. NOTE(@campbellbarton): Blender-as-a-Python-module is too obscure a topic to list directly on the main-page, + so opt for an "Advanced" page which can be expanded on as needed. + +.. toctree:: + :maxdepth: 1 + + info_advanced_blender_as_bpy.rst diff --git a/doc/python_api/rst/info_advanced_blender_as_bpy.rst b/doc/python_api/rst/info_advanced_blender_as_bpy.rst new file mode 100644 index 00000000000..9d2861ff627 --- /dev/null +++ b/doc/python_api/rst/info_advanced_blender_as_bpy.rst @@ -0,0 +1,126 @@ + +************************** +Blender as a Python Module +************************** + +Blender supports being built as a Python module, +allowing ``import bpy`` to be added to any Python script, providing access to Blender's features. + +.. note:: + + At time of writing official builds are not available, + using this requires compiling Blender yourself see + `build instructions <https://wiki.blender.org/w/index.php?title=Building_Blender/Other/BlenderAsPyModule>`__. + + +Use Cases +========= + +Python developers may wish to integrate Blender scripts which don't center around Blender. + +Possible uses include: + +- Visualizing data by rendering images and animations. +- Image processing using Blender's compositor. +- Video editing (using Blender's sequencer). +- 3D file conversion. +- Development, accessing ``bpy`` from Python IDE's and debugging tools for example. +- Automation. + + +Usage +===== + +For the most part using Blender as a Python module is equivalent to running a script in background-mode +(passing the command-line arguments ``--background`` or ``-b``), +however there are some differences to be aware of. + +.. Sorted alphabetically as there isn't an especially a logical order to show them. + +Blender's Executable Access + The attribute :class:`bpy.app.binary_path` defaults to an empty string. + + If you wish to point this to the location of a known executable you may set the value. + + This example searches for the binary, setting it when found: + + .. code-block:: python + + import bpy + import shutil + + blender_bin = shutil.which("blender") + if blender_bin: + print("Found:", blender_bin) + bpy.app.binary_path = blender_bin + else: + print("Unable to find blender!") + +Blender's Internal Modules + There are many modules included with Blender such as :mod:`gpu` and :mod:`mathuils`. + It's important that these are imported after ``bpy`` or they will not be found. + +Command Line Arguments Unsupported + Functionality controlled by command line arguments (shown by calling ``blender --help`` aren't accessible). + + Typically this isn't such a limitation although there are some command line arguments that don't have + equivalents in Blender's Python API (``--threads`` and ``--log`` for example). + + .. note:: + + Access to these settings may be added in the future as needed. + +Resource Sharing (GPU) + It's possible other Python modules make use of the GPU in a way that prevents Blender/Cycles from accessing the GPU. + +Signal Handlers + Blender's typical signal handlers are not initialized, so there is no special handling for ``Control-C`` + to cancel a render and a crash log is not written in the event of a crash. + +Startup and Preferences + When the ``bpy`` module loads it contains the default startup scene + (instead of an "empty" blend-file as you might expect), so there is a default cube, camera and light. + + If you wish to start from an empty file use: ``bpy.ops.wm.read_factory_settings(use_empty=True)``. + + The users startup and preferences are ignored to prevent your local configuration from impacting scripts behavior. + The Python module behaves as if ``--factory-startup`` was passed as a command line argument. + + The users preferences and startup can be loaded using operators: + + .. code-block:: python + + import bpy + + bpy.ops.wm.read_userpref() + bpy.ops.wm.read_homefile() + + +Limitations +=========== + +Most constraints of Blender as an application still apply: + +Reloading Unsupported + Reloading the ``bpy`` module via ``importlib.reload`` will raise an exception + instead of reloading and resetting the module. + + Instead, the operator ``bpy.ops.wm.read_factory_settings()`` can be used to reset the internal state. + +Single Blend File Restriction + Only a single ``.blend`` file can be edited at a time. + + .. hint:: + + As with the application it's possible to start multiple instances, + each with their own ``bpy`` and therefor Blender state. + Python provides the ``multiprocessing`` module to make communicating with sub-processes more convenient. + + In some cases the library API may be an alternative to starting separate processes, + although this API operates on reading and writing ID data-blocks and isn't + a complete substitute for loading ``.blend`` files, see: + + - :meth:`bpy.types.BlendDataLibraries.load` + - :meth:`bpy.types.BlendDataLibraries.write` + - :meth:`bpy.types.BlendData.temp_data` + supports a temporary data-context to avoid manipulating the current ``.blend`` file. diff --git a/doc/python_api/rst/info_api_reference.rst b/doc/python_api/rst/info_api_reference.rst index 70d201016f0..3deb96dbb52 100644 --- a/doc/python_api/rst/info_api_reference.rst +++ b/doc/python_api/rst/info_api_reference.rst @@ -1,6 +1,6 @@ ******************* -Reference API Usage +API Reference Usage ******************* Blender has many interlinking data types which have an auto-generated reference API which often has the information diff --git a/doc/python_api/rst/info_overview.rst b/doc/python_api/rst/info_overview.rst index 50928963f60..638420a53ae 100644 --- a/doc/python_api/rst/info_overview.rst +++ b/doc/python_api/rst/info_overview.rst @@ -1,8 +1,8 @@ .. _info_overview: -******************* -Python API Overview -******************* +************ +API Overview +************ 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 diff --git a/doc/python_api/rst_from_bmesh_opdefines.py b/doc/python_api/rst_from_bmesh_opdefines.py index 3d8ff1e6248..0614538964d 100644 --- a/doc/python_api/rst_from_bmesh_opdefines.py +++ b/doc/python_api/rst_from_bmesh_opdefines.py @@ -241,9 +241,9 @@ def main(): comment_washed = [] comment = [] if comment is None else comment for i, l in enumerate(comment): - assert((l.strip() == "") or - (l in {"/*", " *"}) or - (l.startswith(("/* ", " * ")))) + assert ((l.strip() == "") or + (l in {"/*", " *"}) or + (l.startswith(("/* ", " * ")))) l = l[3:] if i == 0 and not l.strip(): @@ -270,7 +270,7 @@ def main(): tp_sub = None else: print(arg) - assert(0) + assert 0 tp_str = "" @@ -315,7 +315,7 @@ def main(): tp_str += " or any sequence of 3 floats" elif tp == BMO_OP_SLOT_PTR: tp_str = "dict" - assert(tp_sub is not None) + assert tp_sub is not None if tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_BMESH: tp_str = ":class:`bmesh.types.BMesh`" elif tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_SCENE: @@ -330,10 +330,10 @@ def main(): tp_str = ":class:`bpy.types.bpy_struct`" else: print("Can't find", vars_dict_reverse[tp_sub]) - assert(0) + assert 0 elif tp == BMO_OP_SLOT_ELEMENT_BUF: - assert(tp_sub is not None) + assert tp_sub is not None ls = [] if tp_sub & BM_VERT: @@ -342,7 +342,7 @@ def main(): ls.append(":class:`bmesh.types.BMEdge`") if tp_sub & BM_FACE: ls.append(":class:`bmesh.types.BMFace`") - assert(ls) # must be at least one + assert ls # Must be at least one. if tp_sub & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE: tp_str = "/".join(ls) @@ -367,10 +367,10 @@ def main(): tp_str += "unknown internal data, not compatible with python" else: print("Can't find", vars_dict_reverse[tp_sub]) - assert(0) + assert 0 else: print("Can't find", vars_dict_reverse[tp]) - assert(0) + assert 0 args_wash.append((name, tp_str, comment)) return args_wash @@ -394,7 +394,7 @@ def main(): fw(" :return:\n\n") for (name, tp, comment) in args_out_wash: - assert(name.endswith(".out")) + assert name.endswith(".out") name = name[:-4] fw(" - ``%s``: %s\n\n" % (name, comment)) fw(" **type** %s\n" % tp) diff --git a/doc/python_api/sphinx_changelog_gen.py b/doc/python_api/sphinx_changelog_gen.py index 4c9f7232a74..fb93c301280 100644 --- a/doc/python_api/sphinx_changelog_gen.py +++ b/doc/python_api/sphinx_changelog_gen.py @@ -101,7 +101,7 @@ def api_dump(args): version, version_key = api_version() if version is None: - raise(ValueError("API dumps can only be generated from within Blender.")) + raise ValueError("API dumps can only be generated from within Blender.") dump = {} dump_module = dump["bpy.types"] = {} @@ -250,7 +250,7 @@ def api_changelog(args): version, version_key = api_version() if version is None and (filepath_in_from is None or filepath_in_to is None): - raise(ValueError("API dumps files must be given when ran outside of Blender.")) + raise ValueError("API dumps files must be given when ran outside of Blender.") with open(indexpath, 'r', encoding='utf-8') as file_handle: index = json.load(file_handle) @@ -258,17 +258,21 @@ def api_changelog(args): if filepath_in_to is None: filepath_in_to = index.get(version_key, None) if filepath_in_to is None: - raise(ValueError("Cannot find API dump file for Blender version " + str(version) + " in index file.")) + raise ValueError("Cannot find API dump file for Blender version " + str(version) + " in index file.") print("Found to file: %r" % filepath_in_to) if filepath_in_from is None: version_from, version_from_key = api_version_previous_in_index(index, version) if version_from is None: - raise(ValueError("No previous version of Blender could be found in the index.")) + raise ValueError("No previous version of Blender could be found in the index.") filepath_in_from = index.get(version_from_key, None) if filepath_in_from is None: - raise(ValueError("Cannot find API dump file for previous Blender version " + str(version_from) + " in index file.")) + raise ValueError( + "Cannot find API dump file for previous Blender version " + + str(version_from) + + " in index file." + ) print("Found from file: %r" % filepath_in_from) @@ -277,7 +281,7 @@ def api_changelog(args): with open(os.path.join(rootpath, filepath_in_to), 'r', encoding='utf-8') as file_handle: dump_version, dict_to = json.load(file_handle) - assert(tuple(dump_version) == version) + assert tuple(dump_version) == version api_changes = [] @@ -345,8 +349,10 @@ def api_changelog(args): fw("" ":tocdepth: 2\n" "\n" - "Blender API Change Log\n" - "**********************\n" + "Change Log\n" + "**********\n" + "\n" + "Changes in Blender's Python API between releases.\n" "\n" ".. note, this document is auto generated by sphinx_changelog_gen.py\n" "\n" diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 240bec6fd30..f51ab8d6591 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -387,23 +387,35 @@ EXAMPLE_SET_USED = set() # RST files directory. RST_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "rst")) -# extra info, not api reference docs -# stored in ./rst/info_* +# Extra info, not api reference docs stored in `./rst/info_*`. +# Pairs of (file, description), the title makes from the RST files are displayed before the description. INFO_DOCS = ( ("info_quickstart.rst", - "Quickstart: New to Blender or scripting and want to get your feet wet?"), + "New to Blender or scripting and want to get your feet wet?"), ("info_overview.rst", - "API Overview: A more complete explanation of Python integration"), + "A more complete explanation of Python integration."), ("info_api_reference.rst", - "API Reference Usage: examples of how to use the API reference docs"), + "Examples of how to use the API reference docs."), ("info_best_practice.rst", - "Best Practice: Conventions to follow for writing good scripts"), + "Conventions to follow for writing good scripts."), ("info_tips_and_tricks.rst", - "Tips and Tricks: Hints to help you while writing scripts for Blender"), + "Hints to help you while writing scripts for Blender."), ("info_gotcha.rst", - "Gotcha's: Some of the problems you may encounter when writing scripts"), - ("change_log.rst", "Change Log: List of changes since last Blender release"), + "Some of the problems you may encounter when writing scripts."), + ("info_advanced.rst", + "Topics which may not be required for typical usage."), + ("change_log.rst", + "List of changes since last Blender release"), ) +# Referenced indirectly. +INFO_DOCS_OTHER = ( + # Included by: `info_advanced.rst`. + "info_advanced_blender_as_bpy.rst", +) + +# Hide the actual TOC, use a separate list that links to the items. +# This is done so a short description can be included with each link. +USE_INFO_DOCS_FANCY_INDEX = True # only support for properties atm. RNA_BLACKLIST = { @@ -1447,15 +1459,15 @@ def pyrna2sphinx(basepath): # If the link has been written, no need to inline the enum items. enum_text = "" if enum_descr_override else pyrna_enum2sphinx(prop) if prop.name or prop.description or enum_text: - fw(ident + ":%s%s:\n\n" % (id_name, identifier)) + fw(ident + ":%s%s: " % (id_name, identifier)) if prop.name or prop.description: - fw(indent(", ".join(val for val in (prop.name, prop.description) if val), ident + " ") + "\n\n") + fw(", ".join(val for val in (prop.name, prop.description.replace("\n", "")) if val) + "\n") # Special exception, can't use generic code here for enums. if enum_text: - write_indented_lines(ident + " ", fw, enum_text) fw("\n") + write_indented_lines(ident + " ", fw, enum_text) del enum_text # end enum exception @@ -1470,7 +1482,7 @@ def pyrna2sphinx(basepath): struct_module_name = struct.module_name if USE_ONLY_BUILTIN_RNA_TYPES: - assert(struct_module_name == "bpy.types") + assert struct_module_name == "bpy.types" filepath = os.path.join(basepath, "%s.%s.rst" % (struct_module_name, struct.identifier)) file = open(filepath, "w", encoding="utf-8") fw = file.write @@ -1904,7 +1916,7 @@ except ModuleNotFoundError: # fw(" 'collapse_navigation': True,\n") fw(" 'sticky_navigation': False,\n") fw(" 'navigation_depth': 1,\n") - # fw(" 'includehidden': True,\n") + fw(" 'includehidden': False,\n") # fw(" 'titles_only': False\n") fw(" }\n\n") @@ -1976,12 +1988,21 @@ def write_rst_index(basepath): if not EXCLUDE_INFO_DOCS: fw(".. toctree::\n") + if USE_INFO_DOCS_FANCY_INDEX: + fw(" :hidden:\n") fw(" :maxdepth: 1\n") fw(" :caption: Documentation\n\n") for info, info_desc in INFO_DOCS: - fw(" %s <%s>\n" % (info_desc, info)) + fw(" %s\n" % info) fw("\n") + if USE_INFO_DOCS_FANCY_INDEX: + # Show a fake TOC, allowing for an extra description to be shown as well as the title. + fw(title_string("Documentation", "=")) + for info, info_desc in INFO_DOCS: + fw("- :doc:`%s`: %s\n" % (info.removesuffix(".rst"), info_desc)) + fw("\n") + fw(".. toctree::\n") fw(" :maxdepth: 1\n") fw(" :caption: Application Modules\n\n") @@ -2314,6 +2335,8 @@ def copy_handwritten_rsts(basepath): if not EXCLUDE_INFO_DOCS: for info, _info_desc in INFO_DOCS: shutil.copy2(os.path.join(RST_DIR, info), basepath) + for info in INFO_DOCS_OTHER: + shutil.copy2(os.path.join(RST_DIR, info), basepath) # TODO: put this docs in Blender's code and use import as per modules above. handwritten_modules = [ |