PyAPI: add bpy.utils.register_preset_path utility function

Support add-ons including their own preset paths,
needed to resolve #124020.
This commit is contained in:
Campbell Barton 2024-07-16 15:46:22 +10:00
parent e18dcef38d
commit fd5780e97b

View file

@ -25,6 +25,8 @@ __all__ = (
"unregister_cli_command",
"register_manual_map",
"unregister_manual_map",
"register_preset_path",
"unregister_preset_path",
"register_classes_factory",
"register_submodule_factory",
"register_tool",
@ -79,6 +81,9 @@ _script_module_dirs = "startup", "modules"
# it must be in the `BLENDER_SYSTEM_SCRIPTS` by definition and there is no need for a look-up from `_bpy_script_paths`.
_script_base_dir = _os.path.dirname(_os.path.dirname(_os.path.dirname(_os.path.dirname(__file__))))
# Paths managed by `register_preset_path` & `unregister_preset_path`.
_preset_path_registry = set()
def execfile(filepath, *, mod=None):
"""
@ -527,9 +532,57 @@ def preset_paths(subdir):
if _os.path.isdir(directory):
dirs.append(directory)
for path in _preset_path_registry:
directory = _os.path.join(path, "presets", subdir)
if _os.path.isdir(directory):
dirs.append(directory)
return dirs
def register_preset_path(path):
"""
Register a preset search path.
:arg path: preset directory (must be an absolute path).
This path must contain a "presets" subdirectory which will typically contain presets for add-ons.
You may call ``bpy.utils.register_preset_path(os.path.dirname(__file__))`` from an add-ons ``__init__.py`` file.
When the ``__init__.py`` is in the same location as a ``presets`` directory.
For example an operators preset would be located under: ``presets/operator/{operator.id}/``
where ``operator.id`` is the ``bl_idname`` of the operator.
:type path: string
:return: success
:rtype: bool
"""
set_len = len(_preset_path_registry)
_preset_path_registry.add(path)
if set_len == len(_preset_path_registry):
print("Warning: preset path already registered", path)
return False
return True
def unregister_preset_path(path):
"""
Unregister a preset search path.
:arg path: preset directory (must be an absolute path).
This must match the registered path exactly.
:type path: string
:return: success
:rtype: bool
"""
set_len = len(_preset_path_registry)
_preset_path_registry.discard(path)
if set_len == len(_preset_path_registry):
print("Warning: preset path not registered", path)
return False
return True
def is_path_builtin(path):
"""
Returns True if the path is one of the built-in paths used by Blender.