From 8c718557254bc7eb54a2446f30a7548028634e52 Mon Sep 17 00:00:00 2001
From: Jason van Gumster <jason@handturkeystudios.com>
Date: Tue, 25 Jun 2013 15:35:03 +0000
Subject: [PATCH] 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

diff --git a/object_edit_linked.py b/object_edit_linked.py
new file mode 100644
index 000000000..57ff8d0d6
--- /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()
-- 
GitLab