From ea945ab58d856dc61525e8926f093fc6ee9116c9 Mon Sep 17 00:00:00 2001 From: Jason van Gumster Date: Wed, 19 May 2021 14:57:38 -0400 Subject: Edit Linked Library: Added support for linked node groups. Also re-enabled editing from a separate instance of Blender for things in the 3D Viewport as well as in any of the Node Editors. --- object_edit_linked.py | 154 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 143 insertions(+), 11 deletions(-) (limited to 'object_edit_linked.py') diff --git a/object_edit_linked.py b/object_edit_linked.py index b6445981..f27fb82e 100644 --- a/object_edit_linked.py +++ b/object_edit_linked.py @@ -20,10 +20,10 @@ bl_info = { "name": "Edit Linked Library", "author": "Jason van Gumster (Fweeb), Bassam Kurdali, Pablo Vazquez, Rainer Trummer", - "version": (0, 9, 1), + "version": (0, 9, 2), "blender": (2, 80, 0), "location": "File > External Data / View3D > Sidebar > Item Tab", - "description": "Allows editing of objects linked from a .blend library.", + "description": "Allows editing of assets linked from a .blend library.", "doc_url": "{BLENDER_MANUAL_URL}/addons/object/edit_linked_library.html", "category": "Object", } @@ -40,6 +40,7 @@ settings = { "original_file": "", "linked_file": "", "linked_objects": [], + "linked_nodes": [] } @@ -130,6 +131,65 @@ class OBJECT_OT_EditLinked(bpy.types.Operator): return {'FINISHED'} +class NODE_OT_EditLinked(bpy.types.Operator): + """Edit Linked Library""" + bl_idname = "node.edit_linked" + bl_label = "Edit Linked Library" + + use_autosave: bpy.props.BoolProperty( + name="Autosave", + description="Save the current file before opening the linked library", + default=True) + use_instance: bpy.props.BoolProperty( + name="New Blender Instance", + description="Open in a new Blender instance", + default=False) + + @classmethod + def poll(cls, context: bpy.context): + return settings["original_file"] == "" and context.active_node is not None and ( + context.active_node.type == 'GROUP' and + hasattr(context.active_node.node_tree, "library") and + context.active_node.node_tree.library is not None) + + def execute(self, context: bpy.context): + target = context.active_node.node_tree + + targetpath = target.library.filepath + settings["linked_nodes"].append(target.name) + + if targetpath: + logger.debug(target.name + " is linked to " + targetpath) + + if self.use_autosave: + if not bpy.data.filepath: + # File is not saved on disk, better to abort! + self.report({'ERROR'}, "Current file does not exist on disk, we cannot autosave it, aborting") + return {'CANCELLED'} + bpy.ops.wm.save_mainfile() + + settings["original_file"] = bpy.data.filepath + settings["linked_file"] = bpy.path.abspath(targetpath) + + if self.use_instance: + import subprocess + try: + subprocess.Popen([bpy.app.binary_path, settings["linked_file"]]) + except: + logger.error("Error on the new Blender instance") + import traceback + logger.error(traceback.print_exc()) + else: + bpy.ops.wm.open_mainfile(filepath=settings["linked_file"]) + + logger.info("Opened linked file!") + else: + self.report({'WARNING'}, target.name + " is not linked") + logger.warning(target.name + " is not linked") + + return {'FINISHED'} + + class WM_OT_ReturnToOriginal(bpy.types.Operator): """Load the original file""" bl_idname = "wm.return_to_original" @@ -169,16 +229,17 @@ class VIEW3D_PT_PanelLinkedEdit(bpy.types.Panel): return (context.active_object is not None) or (settings["original_file"] != "") def draw_common(self, scene, layout, props): - props.use_autosave = scene.use_autosave - props.use_instance = scene.use_instance + if props is not None: + props.use_autosave = scene.use_autosave + props.use_instance = scene.use_instance - layout.prop(scene, "use_autosave") -# layout.prop(scene, "use_instance") + layout.prop(scene, "use_autosave") + layout.prop(scene, "use_instance") def draw(self, context: bpy.context): scene = context.scene layout = self.layout - layout.use_property_split = True + layout.use_property_split = False layout.use_property_decorate = False icon = "OUTLINER_DATA_" + context.active_object.type.replace("LIGHT_PROBE", "LIGHTPROBE") @@ -222,13 +283,17 @@ class VIEW3D_PT_PanelLinkedEdit(bpy.types.Panel): # XXX - This is for nested linked assets... but it only works # when launching a new Blender instance. Nested links don't # currently work when using a single instance of Blender. - props = layout.operator("object.edit_linked", - text="Edit Library: %s" % context.active_object.instance_collection.name, - icon="LINK_BLEND") + if context.active_object.instance_collection is not None: + props = layout.operator("object.edit_linked", + text="Edit Library: %s" % context.active_object.instance_collection.name, + icon="LINK_BLEND") + else: + props = None self.draw_common(scene, layout, props) - layout.label(text="Path: %s" % + if context.active_object.instance_collection is not None: + layout.label(text="Path: %s" % context.active_object.instance_collection.library.filepath) else: @@ -242,6 +307,71 @@ class VIEW3D_PT_PanelLinkedEdit(bpy.types.Panel): icon=icon) +class NODE_PT_PanelLinkedEdit(bpy.types.Panel): + bl_label = "Edit Linked Library" + bl_space_type = 'NODE_EDITOR' + bl_region_type = 'UI' + bl_category = "Node" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + return context.active_node is not None + + def draw_common(self, scene, layout, props): + if props is not None: + props.use_autosave = scene.use_autosave + props.use_instance = scene.use_instance + + layout.prop(scene, "use_autosave") + layout.prop(scene, "use_instance") + + def draw(self, context): + scene = context.scene + layout = self.layout + layout.use_property_split = False + layout.use_property_decorate = False + icon = 'NODETREE' + + target = context.active_node + + if settings["original_file"] == "" and ( + target.type == 'GROUP' and hasattr(target.node_tree, "library") and + target.node_tree.library is not None): + + props = layout.operator("node.edit_linked", icon="LINK_BLEND", + text="Edit Library: %s" % target.name) + + self.draw_common(scene, layout, props) + + layout.label(text="Path: %s" % target.node_tree.library.filepath) + + elif settings["original_file"] != "": + + if scene.use_instance: + layout.operator("wm.return_to_original", + text="Reload Current File", + icon="FILE_REFRESH").use_autosave = False + + layout.separator() + + props = None + + self.draw_common(scene, layout, props) + + #layout.label(text="Path: %s" % + # context.active_object.instance_collection.library.filepath) + + else: + props = layout.operator("wm.return_to_original", icon="LOOP_BACK") + props.use_autosave = scene.use_autosave + + layout.prop(scene, "use_autosave") + + else: + layout.label(text="%s is not linked" % target.name, icon=icon) + + class TOPBAR_MT_edit_linked_submenu(bpy.types.Menu): bl_label = 'Edit Linked Library' @@ -254,8 +384,10 @@ class TOPBAR_MT_edit_linked_submenu(bpy.types.Menu): addon_keymaps = [] classes = ( OBJECT_OT_EditLinked, + NODE_OT_EditLinked, WM_OT_ReturnToOriginal, VIEW3D_PT_PanelLinkedEdit, + NODE_PT_PanelLinkedEdit, TOPBAR_MT_edit_linked_submenu ) -- cgit v1.2.3