From 8c718557254bc7eb54a2446f30a7548028634e52 Mon Sep 17 00:00:00 2001 From: Jason van Gumster Date: Tue, 25 Jun 2013 15:35:03 +0000 Subject: Moving to trunk (Woohoo!) [[Split portion of a mixed commit.]] --- object_edit_linked.py | 266 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 object_edit_linked.py (limited to 'object_edit_linked.py') diff --git a/object_edit_linked.py b/object_edit_linked.py new file mode 100644 index 00000000..57ff8d0d --- /dev/null +++ b/object_edit_linked.py @@ -0,0 +1,266 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ***** END GPL LICENCE BLOCK ***** + +bl_info = { + "name": "Edit Linked Library", + "author": "Jason van Gumster (Fweeb), Bassam Kurdali, Pablo Vazquez", + "version": (0, 7, 4), + "blender": (2, 65, 0), + "location": "View3D > Toolshelf > Edit Linked Library", + "description": "Allows editing of objects linked from a .blend library.", + "wiki_url": "http://wiki.blender.org/index.php?title=Extensions:2.6/Py/Scripts/Object/Edit_Linked_Library", + "tracker_url": "http://projects.blender.org/tracker/index.php?func=detail&aid=29630", + "category": "Object"} + + +import bpy +from bpy.app.handlers import persistent +import os, subprocess + +settings = { + "original_file": "", + "linked_file": "", + "linked_objects": [], + } + + +@persistent +def linked_file_check(context): + if settings["linked_file"] != "": + if os.path.samefile(settings["linked_file"], bpy.data.filepath): + print("Editing a linked library.") + bpy.ops.object.select_all(action='DESELECT') + for ob_name in settings["linked_objects"]: + bpy.data.objects[ob_name].select = True #XXX Assumes selected object is in the active scene + if len(settings["linked_objects"]) == 1: + bpy.context.scene.objects.active = bpy.data.objects[settings["linked_objects"][0]] + else: + # For some reason, the linked editing session ended + # (failed to find a file or opened a different file + # before returning to the originating .blend) + settings["original_file"] = "" + settings["linked_file"] = "" + + +class EditLinked(bpy.types.Operator): + """Edit Linked Library""" + bl_idname = "object.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): + return settings["original_file"] == "" and ( + (context.active_object.dupli_group and + context.active_object.dupli_group.library is not None) or + context.active_object.library is not None) + #return context.active_object is not None + + def execute(self, context): + #print(bpy.context.active_object.library) + target = context.active_object + + if target.dupli_group and target.dupli_group.library: + targetpath = target.dupli_group.library.filepath + settings["linked_objects"].extend({ob.name for ob in target.dupli_group.objects}) + elif target.library: + targetpath = target.library.filepath + settings["linked_objects"].append(target.name) + + if targetpath: + print(target.name + " is linked to " + targetpath) + + if self.use_autosave: + bpy.ops.wm.save_mainfile() + + settings["original_file"] = bpy.data.filepath + + # XXX: need to test for proxied rigs + settings["linked_file"] = bpy.path.abspath(targetpath) + + if self.use_instance: + try: + subprocess.Popen([bpy.app.binary_path, settings["linked_file"]]) + except: + print("Error on the new Blender instance") + import traceback + traceback.print_exc() + else: + bpy.ops.wm.open_mainfile(filepath=settings["linked_file"]) + + print("Opened linked file!") + else: + self.report({'WARNING'}, target.name + " is not linked") + print(target.name + " is not linked") + + return {'FINISHED'} + + +class ReturnToOriginal(bpy.types.Operator): + """Load the original file""" + bl_idname = "wm.return_to_original" + bl_label = "Return to Original File" + + use_autosave = bpy.props.BoolProperty( + name="Autosave", + description="Save the current file before opening original file", + default=True) + + @classmethod + def poll(cls, context): + return (settings["original_file"] != "") + + def execute(self, context): + if self.use_autosave: + bpy.ops.wm.save_mainfile() + + bpy.ops.wm.open_mainfile(filepath=settings["original_file"]) + + settings["original_file"] = "" + settings["linked_objects"] = [] + print("Back to the original!") + return {'FINISHED'} + + +# UI +# TODO:Add operators to the File menu? +# Hide the entire panel for non-linked objects? +class PanelLinkedEdit(bpy.types.Panel): + bl_label = "Edit Linked Library" + bl_space_type = "VIEW_3D" + bl_region_type = "TOOLS" + + def draw(self, context): + layout = self.layout + scene = context.scene + icon = "OUTLINER_DATA_" + context.active_object.type + + if settings["original_file"] == "" and ( + (context.active_object.dupli_group and + context.active_object.dupli_group.library is not None) or + context.active_object.library is not None): + + if (context.active_object.dupli_group is not None): + props = layout.operator("object.edit_linked", icon="LINK_BLEND", + text="Edit Library: %s" % context.active_object.dupli_group.name) + else: + props = layout.operator("object.edit_linked", icon="LINK_BLEND", + text="Edit Library: %s" % context.active_object.name) + props.use_autosave = scene.use_autosave + props.use_instance = scene.use_instance + + layout.prop(scene, "use_autosave") + layout.prop(scene, "use_instance") + + if (context.active_object.dupli_group is not None): + layout.label(text="Path: %s" % + context.active_object.dupli_group.library.filepath) + else: + layout.label(text="Path: %s" % + context.active_object.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() + + #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.dupli_group.name, + icon="LINK_BLEND") + props.use_autosave = scene.use_autosave + props.use_instance = scene.use_instance + layout.prop(scene, "use_autosave") + layout.prop(scene, "use_instance") + + layout.label(text="Path: %s" % + context.active_object.dupli_group.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" % context.active_object.name, + icon=icon) + + +addon_keymaps = [] + + +def register(): + bpy.app.handlers.load_post.append(linked_file_check) + bpy.utils.register_class(EditLinked) + bpy.utils.register_class(ReturnToOriginal) + bpy.utils.register_class(PanelLinkedEdit) + + # Is there a better place to store this properties? + bpy.types.Scene.use_autosave = bpy.props.BoolProperty( + name="Autosave", + description="Save the current file before opening a linked file", + default=True) + bpy.types.Scene.use_instance = bpy.props.BoolProperty( + name="New Blender Instance", + description="Open in a new Blender instance", + default=False) + + # Keymapping (deactivated by default; activated when a library object is selected) + kc = bpy.context.window_manager.keyconfigs.addon + km = kc.keymaps.new(name="3D View", space_type='VIEW_3D') + kmi = km.keymap_items.new("object.edit_linked", 'NUMPAD_SLASH', 'PRESS', shift=True) + kmi.active = True + addon_keymaps.append((km, kmi)) + kmi = km.keymap_items.new("wm.return_to_original", 'NUMPAD_SLASH', 'PRESS', shift=True) + kmi.active = True + addon_keymaps.append((km, kmi)) + + +def unregister(): + bpy.utils.unregister_class(EditLinked) + bpy.utils.unregister_class(ReturnToOriginal) + bpy.utils.unregister_class(PanelLinkedEdit) + bpy.app.handlers.load_post.remove(linked_file_check) + + del bpy.types.Scene.use_autosave + del bpy.types.Scene.use_instance + + # handle the keymap + for km, kmi in addon_keymaps: + km.keymap_items.remove(kmi) + addon_keymaps.clear() + + +if __name__ == "__main__": + register() -- cgit v1.2.3