From 9d76f9d50c52e0208c2bdf3be797c38eeab14dda Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Thu, 15 Dec 2022 16:53:03 +0000 Subject: [PATCH 1/7] Implemented workfile importer --- .../blender/plugins/load/import_workfile.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 openpype/hosts/blender/plugins/load/import_workfile.py diff --git a/openpype/hosts/blender/plugins/load/import_workfile.py b/openpype/hosts/blender/plugins/load/import_workfile.py new file mode 100644 index 0000000000..3b9edbc8c7 --- /dev/null +++ b/openpype/hosts/blender/plugins/load/import_workfile.py @@ -0,0 +1,38 @@ +from pathlib import Path + +import bpy + +from openpype.hosts.blender.api import plugin + + +class ImportBlendLoader(plugin.AssetLoader): + """Import action for Blender (unmanaged) + + Warning: + The loaded content will be unmanaged and is *not* visible in the + scene inventory. It's purely intended to merge content into your scene + so you could also use it as a new base. + + """ + + representations = ["blend"] + families = ["*"] + + label = "Import" + order = 10 + icon = "arrow-circle-down" + color = "#775555" + + def load(self, context, name=None, namespace=None, data=None): + scene = bpy.context.scene + + with bpy.data.libraries.load(self.fname) as (data_from, data_to): + for attr in dir(data_to): + setattr(data_to, attr, getattr(data_from, attr)) + + # Add objects to current scene + # for obj in data_to.objects: + # scene.collection.objects.link(obj) + + # We do not containerize imported content, it remains unmanaged + return From d935b9b689ddff657056cf92cabb5be9a5b0be3f Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Thu, 15 Dec 2022 16:57:59 +0000 Subject: [PATCH 2/7] Hound fixes --- openpype/hosts/blender/plugins/load/import_workfile.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openpype/hosts/blender/plugins/load/import_workfile.py b/openpype/hosts/blender/plugins/load/import_workfile.py index 3b9edbc8c7..14c970c8d9 100644 --- a/openpype/hosts/blender/plugins/load/import_workfile.py +++ b/openpype/hosts/blender/plugins/load/import_workfile.py @@ -1,5 +1,3 @@ -from pathlib import Path - import bpy from openpype.hosts.blender.api import plugin @@ -24,13 +22,12 @@ class ImportBlendLoader(plugin.AssetLoader): color = "#775555" def load(self, context, name=None, namespace=None, data=None): - scene = bpy.context.scene - with bpy.data.libraries.load(self.fname) as (data_from, data_to): for attr in dir(data_to): setattr(data_to, attr, getattr(data_from, attr)) # Add objects to current scene + # scene = bpy.context.scene # for obj in data_to.objects: # scene.collection.objects.link(obj) From 2a49265ba7c23c965754d5ed1c5ee59bfd7e058f Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Fri, 16 Dec 2022 10:59:51 +0000 Subject: [PATCH 3/7] Renamed to "Append workfile" --- openpype/hosts/blender/plugins/load/import_workfile.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/blender/plugins/load/import_workfile.py b/openpype/hosts/blender/plugins/load/import_workfile.py index 14c970c8d9..244eefe936 100644 --- a/openpype/hosts/blender/plugins/load/import_workfile.py +++ b/openpype/hosts/blender/plugins/load/import_workfile.py @@ -3,20 +3,19 @@ import bpy from openpype.hosts.blender.api import plugin -class ImportBlendLoader(plugin.AssetLoader): - """Import action for Blender (unmanaged) +class AppendBlendLoader(plugin.AssetLoader): + """Append workfile in Blender (unmanaged) Warning: The loaded content will be unmanaged and is *not* visible in the scene inventory. It's purely intended to merge content into your scene so you could also use it as a new base. - """ representations = ["blend"] families = ["*"] - label = "Import" + label = "Append Workfile" order = 10 icon = "arrow-circle-down" color = "#775555" From c053762fedc29289d0e1d03fd0f0a012d2923c81 Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Fri, 16 Dec 2022 11:17:34 +0000 Subject: [PATCH 4/7] Differentiate Append and Import loaders --- .../blender/plugins/load/import_workfile.py | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/blender/plugins/load/import_workfile.py b/openpype/hosts/blender/plugins/load/import_workfile.py index 244eefe936..2849031f7e 100644 --- a/openpype/hosts/blender/plugins/load/import_workfile.py +++ b/openpype/hosts/blender/plugins/load/import_workfile.py @@ -16,7 +16,7 @@ class AppendBlendLoader(plugin.AssetLoader): families = ["*"] label = "Append Workfile" - order = 10 + order = 9 icon = "arrow-circle-down" color = "#775555" @@ -25,10 +25,37 @@ class AppendBlendLoader(plugin.AssetLoader): for attr in dir(data_to): setattr(data_to, attr, getattr(data_from, attr)) + # We do not containerize imported content, it remains unmanaged + return + +class ImportBlendLoader(plugin.AssetLoader): + """Import workfile in the current Blender scene (unmanaged) + + Warning: + The loaded content will be unmanaged and is *not* visible in the + scene inventory. It's purely intended to merge content into your scene + so you could also use it as a new base. + """ + + representations = ["blend"] + families = ["*"] + + label = "Import Workfile" + order = 9 + icon = "arrow-circle-down" + color = "#775555" + + def load(self, context, name=None, namespace=None, data=None): + with bpy.data.libraries.load(self.fname) as (data_from, data_to): + for attr in dir(data_to): + if attr == "scenes": + continue + setattr(data_to, attr, getattr(data_from, attr)) + # Add objects to current scene - # scene = bpy.context.scene - # for obj in data_to.objects: - # scene.collection.objects.link(obj) + scene = bpy.context.scene + for obj in data_to.objects: + scene.collection.objects.link(obj) # We do not containerize imported content, it remains unmanaged return From a0c60afb286bb615b67aa3e0fa156767f3c167e5 Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Fri, 16 Dec 2022 14:46:29 +0000 Subject: [PATCH 5/7] Objects imported are stored in collections for each scene --- .../blender/plugins/load/import_workfile.py | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/blender/plugins/load/import_workfile.py b/openpype/hosts/blender/plugins/load/import_workfile.py index 2849031f7e..ed24140a59 100644 --- a/openpype/hosts/blender/plugins/load/import_workfile.py +++ b/openpype/hosts/blender/plugins/load/import_workfile.py @@ -1,8 +1,20 @@ +from pathlib import Path + import bpy from openpype.hosts.blender.api import plugin +def get_unique_number(asset, subset): + count = 1 + name = f"{asset}_{count:0>2}_{subset}" + collection_names = [coll.name for coll in bpy.data.collections] + while name in collection_names: + count += 1 + name = f"{asset}_{count:0>2}_{subset}" + return f"{count:0>2}" + + class AppendBlendLoader(plugin.AssetLoader): """Append workfile in Blender (unmanaged) @@ -28,6 +40,7 @@ class AppendBlendLoader(plugin.AssetLoader): # We do not containerize imported content, it remains unmanaged return + class ImportBlendLoader(plugin.AssetLoader): """Import workfile in the current Blender scene (unmanaged) @@ -46,16 +59,26 @@ class ImportBlendLoader(plugin.AssetLoader): color = "#775555" def load(self, context, name=None, namespace=None, data=None): + asset = context['asset']['name'] + subset = context['subset']['name'] + + unique_number = get_unique_number(asset, subset) + group_name = plugin.asset_name(asset, subset, unique_number) + with bpy.data.libraries.load(self.fname) as (data_from, data_to): for attr in dir(data_to): - if attr == "scenes": - continue setattr(data_to, attr, getattr(data_from, attr)) - # Add objects to current scene - scene = bpy.context.scene - for obj in data_to.objects: - scene.collection.objects.link(obj) + current_scene = bpy.context.scene + + for scene in data_to.scenes: + # scene.name = group_name + collection = bpy.data.collections.new(name=group_name) + for obj in scene.objects: + collection.objects.link(obj) + current_scene.collection.children.link(collection) + for coll in scene.collection.children: + collection.children.link(coll) # We do not containerize imported content, it remains unmanaged return From f94a4195eb63662cdd70f17796c4c31f1265922b Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Fri, 16 Dec 2022 14:47:28 +0000 Subject: [PATCH 6/7] The original names of the scenes are now preserved --- .../hosts/blender/plugins/load/import_workfile.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/blender/plugins/load/import_workfile.py b/openpype/hosts/blender/plugins/load/import_workfile.py index ed24140a59..92f5ba168c 100644 --- a/openpype/hosts/blender/plugins/load/import_workfile.py +++ b/openpype/hosts/blender/plugins/load/import_workfile.py @@ -65,15 +65,22 @@ class ImportBlendLoader(plugin.AssetLoader): unique_number = get_unique_number(asset, subset) group_name = plugin.asset_name(asset, subset, unique_number) + # We need to preserve the original names of the scenes, otherwise, + # if there are duplicate names in the current workfile, the imported + # scenes will be renamed by Blender to avoid conflicts. + original_scene_names = [] + with bpy.data.libraries.load(self.fname) as (data_from, data_to): for attr in dir(data_to): + if attr == "scenes": + for scene in data_from.scenes: + original_scene_names.append(scene) setattr(data_to, attr, getattr(data_from, attr)) current_scene = bpy.context.scene - for scene in data_to.scenes: - # scene.name = group_name - collection = bpy.data.collections.new(name=group_name) + for scene, s_name in zip(data_to.scenes, original_scene_names): + collection = bpy.data.collections.new(f"{group_name}_{s_name}") for obj in scene.objects: collection.objects.link(obj) current_scene.collection.children.link(collection) From 9d57af05615ccf93943600f5af6fc1e8dfaad983 Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Fri, 16 Dec 2022 14:59:39 +0000 Subject: [PATCH 7/7] Scenes are renamed to identify from where they have been loaded --- .../blender/plugins/load/import_workfile.py | 71 ++++++++----------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/openpype/hosts/blender/plugins/load/import_workfile.py b/openpype/hosts/blender/plugins/load/import_workfile.py index 92f5ba168c..618fb83e31 100644 --- a/openpype/hosts/blender/plugins/load/import_workfile.py +++ b/openpype/hosts/blender/plugins/load/import_workfile.py @@ -1,18 +1,37 @@ -from pathlib import Path - import bpy from openpype.hosts.blender.api import plugin -def get_unique_number(asset, subset): - count = 1 - name = f"{asset}_{count:0>2}_{subset}" - collection_names = [coll.name for coll in bpy.data.collections] - while name in collection_names: - count += 1 - name = f"{asset}_{count:0>2}_{subset}" - return f"{count:0>2}" +def append_workfile(context, fname, do_import): + asset = context['asset']['name'] + subset = context['subset']['name'] + + group_name = plugin.asset_name(asset, subset) + + # We need to preserve the original names of the scenes, otherwise, + # if there are duplicate names in the current workfile, the imported + # scenes will be renamed by Blender to avoid conflicts. + original_scene_names = [] + + with bpy.data.libraries.load(fname) as (data_from, data_to): + for attr in dir(data_to): + if attr == "scenes": + for scene in data_from.scenes: + original_scene_names.append(scene) + setattr(data_to, attr, getattr(data_from, attr)) + + current_scene = bpy.context.scene + + for scene, s_name in zip(data_to.scenes, original_scene_names): + scene.name = f"{group_name}_{s_name}" + if do_import: + collection = bpy.data.collections.new(f"{group_name}_{s_name}") + for obj in scene.objects: + collection.objects.link(obj) + current_scene.collection.children.link(collection) + for coll in scene.collection.children: + collection.children.link(coll) class AppendBlendLoader(plugin.AssetLoader): @@ -33,9 +52,7 @@ class AppendBlendLoader(plugin.AssetLoader): color = "#775555" def load(self, context, name=None, namespace=None, data=None): - with bpy.data.libraries.load(self.fname) as (data_from, data_to): - for attr in dir(data_to): - setattr(data_to, attr, getattr(data_from, attr)) + append_workfile(context, self.fname, False) # We do not containerize imported content, it remains unmanaged return @@ -59,33 +76,7 @@ class ImportBlendLoader(plugin.AssetLoader): color = "#775555" def load(self, context, name=None, namespace=None, data=None): - asset = context['asset']['name'] - subset = context['subset']['name'] - - unique_number = get_unique_number(asset, subset) - group_name = plugin.asset_name(asset, subset, unique_number) - - # We need to preserve the original names of the scenes, otherwise, - # if there are duplicate names in the current workfile, the imported - # scenes will be renamed by Blender to avoid conflicts. - original_scene_names = [] - - with bpy.data.libraries.load(self.fname) as (data_from, data_to): - for attr in dir(data_to): - if attr == "scenes": - for scene in data_from.scenes: - original_scene_names.append(scene) - setattr(data_to, attr, getattr(data_from, attr)) - - current_scene = bpy.context.scene - - for scene, s_name in zip(data_to.scenes, original_scene_names): - collection = bpy.data.collections.new(f"{group_name}_{s_name}") - for obj in scene.objects: - collection.objects.link(obj) - current_scene.collection.children.link(collection) - for coll in scene.collection.children: - collection.children.link(coll) + append_workfile(context, self.fname, True) # We do not containerize imported content, it remains unmanaged return