Docs: Grammar and wording cleanups for FileHandler examples

Cleanup grammar and simplify the wording used in the FileHandler
Python API examples.

Pull Request: https://projects.blender.org/blender/blender/pulls/139366
This commit is contained in:
Jesse Yurkovich
2025-06-02 19:21:38 +02:00
committed by Jesse Yurkovich
parent 2add72df04
commit 0fa8c0f62a
2 changed files with 57 additions and 48 deletions

View File

@@ -1,25 +1,20 @@
"""
Basic FileHandler for Operator that imports just one file
---------------------------------------------------------
Basic FileHandler for importing a single file
---------------------------------------------
When creating a ``Operator`` that imports files, you may want to
add them 'drag-and-drop' support, File Handlers helps to define
a set of files extensions (:class:`FileHandler.bl_file_extensions`)
that the ``Operator`` support and a :class:`FileHandler.poll_drop`
function that can be used to check in what specific context the ``Operator``
can be invoked with 'drag-and-drop' filepath data.
A file handler allows custom 'drag-and-drop' behavior to be associated with a given ``Operator``
(:class:`FileHandler.bl_import_operator`) and set of file extensions
(:class:`FileHandler.bl_file_extensions`). Control over which area of the UI accepts the
`drag-in-drop` action is specified using the :class:`FileHandler.poll_drop` method.
Same as operators that uses the file select window, this operators
required a set of properties, when the ``Operator`` can import just one
file per execution it needs to define the following property:
Similar to operators that use a file select window, operators participating in 'drag-and-drop', and
only accepting a single file, must define the following property:
.. code-block:: python
filepath: bpy.props.StringProperty(subtype='FILE_PATH')
This ``filepath`` property now will be used by the ``FileHandler`` to
set the 'drag-and-drop' filepath data.
filepath: bpy.props.StringProperty(subtype='FILE_PATH', options={'SKIP_SAVE'})
This ``filepath`` property will be set to the full path of the file dropped by the user.
"""
import bpy
@@ -27,13 +22,13 @@ import bpy
class CurveTextImport(bpy.types.Operator):
"""
Test importer that creates a text object from a text file.
Creates a text object from a text file.
"""
bl_idname = "curve.text_import"
bl_label = "Import a text file as text object"
# This Operator supports import one `.txt` file at the time, we need the
# following file-path property that the file handler will use to set file path data.
# This Operator supports processing one `.txt` file at a time. The following file-path
# property must be defined.
filepath: bpy.props.StringProperty(subtype='FILE_PATH', options={'SKIP_SAVE'})
@classmethod
@@ -41,10 +36,12 @@ class CurveTextImport(bpy.types.Operator):
return (context.area and context.area.type == "VIEW_3D")
def execute(self, context):
# Calls to this Operator can set unfiltered file-paths, ensure the file extension is `.txt`.
# Direct calls to this Operator may use unsupported file-paths. Ensure the incoming
# file-path is one that is supported.
if not self.filepath or not self.filepath.endswith(".txt"):
return {'CANCELLED'}
# Create a Blender Text object from the contents of the provided file.
with open(self.filepath) as file:
text_curve = bpy.data.curves.new(type="FONT", name="Text")
text_curve.body = ''.join(file.readlines())
@@ -52,11 +49,12 @@ class CurveTextImport(bpy.types.Operator):
bpy.context.scene.collection.objects.link(text_object)
return {'FINISHED'}
# By default the file handler invokes the operator with the file-path property set.
# In this example if this property is set the operator is executed, if not the
# file select window is invoked.
# This depends on setting `options={'SKIP_SAVE'}` to the property options to avoid
# to reuse file-path data between operator calls.
# By default the file handler invokes the operator with the file-path property set. If the
# operator also supports being invoked with no file-path set, and allows the user to pick from a
# file select window instead, the following logic can be used.
#
# Note: It is important to use `options={'SKIP_SAVE'}` when defining the file-path property to
# avoid prior values from being reused on subsequent calls.
def invoke(self, context, event):
if self.filepath:
@@ -65,6 +63,9 @@ class CurveTextImport(bpy.types.Operator):
return {'RUNNING_MODAL'}
# Define a file handler that supports the following set of conditions:
# - Execute the `curve.text_import` operator
# - When `.txt` files are dropped in the 3D Viewport
class CURVE_FH_text_import(bpy.types.FileHandler):
bl_idname = "CURVE_FH_text_import"
bl_label = "File handler for curve text object import"

View File

@@ -1,17 +1,21 @@
"""
Basic FileHandler for Operator that imports multiple files
----------------------------------------------------------
FileHandler for Importing multiple files and exposing Operator options
----------------------------------------------------------------------
Also operators can be invoked with multiple files from 'drag-and-drop',
but for this it is require to define the following properties:
Operators which support being executed with multiple files from 'drag-and-drop' require the
following properties be defined:
.. code-block:: python
directory: StringProperty(subtype='DIR_PATH')
files: CollectionProperty(type=bpy.types.OperatorFileListElement)
directory: StringProperty(subtype='DIR_PATH', options={'SKIP_SAVE', 'HIDDEN'})
files: CollectionProperty(type=OperatorFileListElement, options={'SKIP_SAVE', 'HIDDEN'})
This ``directory`` and ``files`` properties now will be used by the
``FileHandler`` to set 'drag-and-drop' filepath data.
These ``directory`` and ``files`` properties will be set with the necessary data from the
`drag-and-drop` operation.
Additionally, if the operator provides operator properties that need to be accessible to the user,
the :class:`ImportHelper.invoke_popup` method can be used to show a dialog leveraging the standard
:class:`Operator.draw` method for layout and display.
"""
@@ -21,18 +25,18 @@ from mathutils import Vector
class ShaderScriptImport(bpy.types.Operator, ImportHelper):
"""Test importer that creates scripts nodes from .txt files"""
"""
Creates one or more Shader Script nodes from text files.
"""
bl_idname = "shader.script_import"
bl_label = "Import a text file as a script node"
"""
This Operator can import multiple .txt files, we need following directory and files
properties that the file handler will use to set files path data
"""
# This Operator supports processing multiple `.txt` files at a time. The following properties
# must be defined.
directory: bpy.props.StringProperty(subtype='DIR_PATH', options={'SKIP_SAVE', 'HIDDEN'})
files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement, options={'SKIP_SAVE', 'HIDDEN'})
"""Allow the user to select if the node's label is set or not"""
# Allow the user to choose whether the node's label is set or not
set_label: bpy.props.BoolProperty(name="Set Label", default=False)
@classmethod
@@ -45,22 +49,22 @@ class ShaderScriptImport(bpy.types.Operator, ImportHelper):
)
def execute(self, context):
""" The directory property need to be set. """
# The directory property must be set.
if not self.directory:
return {'CANCELLED'}
x = 0.0
y = 0.0
for file in self.files:
"""
Calls to the operator can set unfiltered file names,
ensure the file extension is .txt
"""
# Direct calls to this Operator may use unsupported file-paths. Ensure the incoming
# files are ones that are supported.
if file.name.endswith(".txt"):
import os
filepath = os.path.join(self.directory, file.name)
node_tree = context.material.node_tree
text_node = node_tree.nodes.new(type="ShaderNodeScript")
text_node.mode = 'EXTERNAL'
import os
filepath = os.path.join(self.directory, file.name)
text_node.filepath = filepath
text_node.location = Vector((x, y))
@@ -70,12 +74,13 @@ class ShaderScriptImport(bpy.types.Operator, ImportHelper):
x += 20.0
y -= 20.0
return {'FINISHED'}
# Use ImportHelper's invoke_popup() to handle the invocation so that this operator's properties
# are shown in a popup. This allows the user to configure additional settings on the operator like
# the `set_label` property. Consider having a draw() method on the operator in order to layout the
# properties in the UI appropriately.
# are shown in a popup. This allows the user to configure additional settings on the operator
# like the `set_label` property. Consider having a draw() method on the operator in order to
# layout the properties in the UI appropriately.
#
# If filepath information is not provided the file select window will be invoked instead.
@@ -83,6 +88,9 @@ class ShaderScriptImport(bpy.types.Operator, ImportHelper):
return self.invoke_popup(context)
# Define a file handler that supports the following set of conditions:
# - Execute the `shader.script_import` operator
# - When `.txt` files are dropped in the Shader Editor
class SHADER_FH_script_import(bpy.types.FileHandler):
bl_idname = "SHADER_FH_script_import"
bl_label = "File handler for shader script node import"