diff options
author | Sybren A. Stüvel <sybren@blender.org> | 2021-07-02 11:40:19 +0300 |
---|---|---|
committer | Sybren A. Stüvel <sybren@blender.org> | 2021-07-15 17:12:36 +0300 |
commit | b40e05fcd134e5b9d5aac7ba9e5f45e4e9733607 (patch) | |
tree | 800b488d96fff7a0329768322a6adc0a9c7e466d /release/scripts/startup/bl_operators | |
parent | 637731dc610370782b1041ece4425bf3e6086ba0 (diff) |
Assets: Open Blend File operator
Add operator 'Open Blend File' to the Asset Browser. This operator:
- starts a new Blender process,
- opens the blend file containing the asset,
- monitors the new Blender process, and when it stops,
- reloads the assets to show any changes made.
Diffstat (limited to 'release/scripts/startup/bl_operators')
-rw-r--r-- | release/scripts/startup/bl_operators/assets.py | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/release/scripts/startup/bl_operators/assets.py b/release/scripts/startup/bl_operators/assets.py index 48f07a03773..d2655784afd 100644 --- a/release/scripts/startup/bl_operators/assets.py +++ b/release/scripts/startup/bl_operators/assets.py @@ -18,7 +18,9 @@ # <pep8 compliant> from __future__ import annotations +from pathlib import Path +import bpy from bpy.types import Operator from bpy_extras.asset_utils import ( @@ -72,7 +74,88 @@ class ASSET_OT_tag_remove(Operator): return {'FINISHED'} +class ASSET_OT_open_containing_blend_file(Operator): + """Open the blend file that contains the active asset""" + + bl_idname = "asset.open_containing_blend_file" + bl_label = "Open Blend File" + bl_options = {'REGISTER'} + + _process = None # Optional[subprocess.Popen] + + @classmethod + def poll(cls, context): + asset_file_handle = getattr(context, 'asset_file_handle', None) + asset_library = getattr(context, 'asset_library', None) + + if not asset_library: + cls.poll_message_set("No asset library selected") + return False + if not asset_file_handle: + cls.poll_message_set("No asset selected") + return False + if asset_file_handle.local_id: + cls.poll_message_set("Selected asset is contained in the current file") + return False + return True + + def execute(self, context): + asset_file_handle = context.asset_file_handle + asset_library = context.asset_library + + if asset_file_handle.local_id: + self.report({'WARNING'}, "This asset is stored in the current blend file") + return {'CANCELLED'} + + asset_lib_path = bpy.types.AssetHandle.get_full_library_path(asset_file_handle, asset_library) + self.open_in_new_blender(asset_lib_path) + + wm = context.window_manager + self._timer = wm.event_timer_add(0.1, window=context.window) + wm.modal_handler_add(self) + + return {'RUNNING_MODAL'} + + def modal(self, context, event): + if event.type != 'TIMER': + return {'PASS_THROUGH'} + + if self._process is None: + self.report({'ERROR'}, "Unable to find any running process") + self.cancel(context) + return {'CANCELLED'} + + returncode = self._process.poll() + if returncode is None: + # Process is still running. + return {'RUNNING_MODAL'} + + if returncode: + self.report({'WARNING'}, "Blender subprocess exited with error code %d" % returncode) + + # TODO(Sybren): Replace this with a generic "reload assets" operator + # that can run outside of the Asset Browser context. + if bpy.ops.file.refresh.poll(): + bpy.ops.file.refresh() + if bpy.ops.asset.list_refresh.poll(): + bpy.ops.asset.list_refresh() + + self.cancel(context) + return {'FINISHED'} + + def cancel(self, context): + wm = context.window_manager + wm.event_timer_remove(self._timer) + + def open_in_new_blender(self, filepath): + import subprocess + + cli_args = [bpy.app.binary_path, str(filepath)] + self._process = subprocess.Popen(cli_args) + + classes = ( ASSET_OT_tag_add, ASSET_OT_tag_remove, + ASSET_OT_open_containing_blend_file, ) |