From a0096d6cdf062c81fb1c4c9dc13e27aa49da73f6 Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Thu, 25 Jun 2020 11:14:06 +0100 Subject: [PATCH] Rig support for namespaces --- pype/plugins/blender/load/load_model.py | 21 ++++----- pype/plugins/blender/load/load_rig.py | 60 +++++++++++++------------ 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/pype/plugins/blender/load/load_model.py b/pype/plugins/blender/load/load_model.py index b16f5a40b1..6f34b40e70 100644 --- a/pype/plugins/blender/load/load_model.py +++ b/pype/plugins/blender/load/load_model.py @@ -17,10 +17,6 @@ class BlendModelLoader(plugin.AssetLoader): Because they come from a .blend file we can simply link the collection that contains the model. There is no further need to 'containerise' it. - - Warning: - Loading the same asset more then once is not properly supported at the - moment. """ families = ["model"] @@ -102,16 +98,16 @@ class BlendModelLoader(plugin.AssetLoader): asset, subset, namespace ) - collection = bpy.data.collections.new(lib_container) + container = bpy.data.collections.new(lib_container) blender.pipeline.containerise_existing( - collection, + container, name, namespace, context, self.__class__.__name__, ) - container_metadata = collection.get( + container_metadata = container.get( blender.pipeline.AVALON_PROPERTY) container_metadata["libpath"] = libpath @@ -125,8 +121,8 @@ class BlendModelLoader(plugin.AssetLoader): # Save the list of objects in the metadata container container_metadata["objects"] = obj_container.all_objects - nodes = list(collection.objects) - nodes.append(collection) + nodes = list(container.objects) + nodes.append(container) self[:] = nodes return nodes @@ -148,7 +144,7 @@ class BlendModelLoader(plugin.AssetLoader): libpath = Path(api.get_representation_path(representation)) extension = libpath.suffix.lower() - logger.debug( + logger.info( "Container: %s\nRepresentation: %s", pformat(container, indent=2), pformat(representation, indent=2), @@ -194,11 +190,12 @@ class BlendModelLoader(plugin.AssetLoader): self._remove(objects, obj_container) - objects_list = self._process( + obj_container = self._process( str(libpath), lib_container, collection.name) # Save the list of objects in the metadata container - collection_metadata["objects"] = objects_list + collection_metadata["obj_container"] = obj_container + collection_metadata["objects"] = obj_container.all_objects collection_metadata["libpath"] = str(libpath) collection_metadata["representation"] = str(representation["_id"]) diff --git a/pype/plugins/blender/load/load_rig.py b/pype/plugins/blender/load/load_rig.py index 3e53ff0363..41343e9c3a 100644 --- a/pype/plugins/blender/load/load_rig.py +++ b/pype/plugins/blender/load/load_rig.py @@ -7,20 +7,16 @@ from typing import Dict, List, Optional from avalon import api, blender import bpy -import pype.hosts.blender.plugin +import pype.hosts.blender.plugin as plugin -logger = logging.getLogger("pype").getChild("blender").getChild("load_model") +logger = logging.getLogger("pype").getChild("blender").getChild("load_rig") -class BlendRigLoader(pype.hosts.blender.plugin.AssetLoader): +class BlendRigLoader(plugin.AssetLoader): """Load rigs from a .blend file. Because they come from a .blend file we can simply link the collection that contains the model. There is no further need to 'containerise' it. - - Warning: - Loading the same asset more then once is not properly supported at the - moment. """ families = ["rig"] @@ -33,7 +29,6 @@ class BlendRigLoader(pype.hosts.blender.plugin.AssetLoader): def _remove(self, objects, lib_container): for obj in objects: - if obj.type == 'ARMATURE': bpy.data.armatures.remove(obj.data) elif obj.type == 'MESH': @@ -44,8 +39,12 @@ class BlendRigLoader(pype.hosts.blender.plugin.AssetLoader): bpy.data.collections.remove(bpy.data.collections[lib_container]) - def _process(self, libpath, lib_container, container_name, action): + def prepare_data(self, data, container_name): + name = data.name + data = data.make_local() + data.name = f"{name}:{container_name}" + def _process(self, libpath, lib_container, container_name, action): relative = bpy.context.preferences.filepaths.use_relative_paths with bpy.data.libraries.load( libpath, link=True, relative=relative @@ -57,6 +56,7 @@ class BlendRigLoader(pype.hosts.blender.plugin.AssetLoader): scene.collection.children.link(bpy.data.collections[lib_container]) rig_container = scene.collection.children[lib_container].make_local() + rig_container.name = container_name meshes = [] armatures = [ @@ -65,15 +65,15 @@ class BlendRigLoader(pype.hosts.blender.plugin.AssetLoader): objects_list = [] for child in rig_container.children: - child.make_local() + self.prepare_data(child, container_name) meshes.extend( child.objects ) # Link meshes first, then armatures. # The armature is unparented for all the non-local meshes, # when it is made local. for obj in meshes + armatures: - obj = obj.make_local() - obj.data.make_local() + self.prepare_data(obj, container_name) + self.prepare_data(obj.data, container_name) if not obj.get(blender.pipeline.AVALON_PROPERTY): obj[blender.pipeline.AVALON_PROPERTY] = dict() @@ -84,13 +84,11 @@ class BlendRigLoader(pype.hosts.blender.plugin.AssetLoader): if obj.type == 'ARMATURE' and action is not None: obj.animation_data.action = action - objects_list.append(obj) - rig_container.pop(blender.pipeline.AVALON_PROPERTY) bpy.ops.object.select_all(action='DESELECT') - return objects_list + return rig_container def process_asset( self, context: dict, name: str, namespace: Optional[str] = None, @@ -107,13 +105,17 @@ class BlendRigLoader(pype.hosts.blender.plugin.AssetLoader): libpath = self.fname asset = context["asset"]["name"] subset = context["subset"]["name"] - lib_container = pype.hosts.blender.plugin.asset_name(asset, subset) - container_name = pype.hosts.blender.plugin.asset_name( + lib_container = plugin.asset_name( + asset, subset + ) + namespace = namespace or plugin.asset_namespace( + asset, subset + ) + container_name = plugin.asset_name( asset, subset, namespace ) container = bpy.data.collections.new(lib_container) - container.name = container_name blender.pipeline.containerise_existing( container, name, @@ -128,11 +130,13 @@ class BlendRigLoader(pype.hosts.blender.plugin.AssetLoader): container_metadata["libpath"] = libpath container_metadata["lib_container"] = lib_container - objects_list = self._process( + obj_container = self._process( libpath, lib_container, container_name, None) + container_metadata["obj_container"] = obj_container + # Save the list of objects in the metadata container - container_metadata["objects"] = objects_list + container_metadata["objects"] = obj_container.all_objects nodes = list(container.objects) nodes.append(container) @@ -151,11 +155,9 @@ class BlendRigLoader(pype.hosts.blender.plugin.AssetLoader): Warning: No nested collections are supported at the moment! """ - collection = bpy.data.collections.get( container["objectName"] ) - libpath = Path(api.get_representation_path(representation)) extension = libpath.suffix.lower() @@ -177,7 +179,7 @@ class BlendRigLoader(pype.hosts.blender.plugin.AssetLoader): assert libpath.is_file(), ( f"The file doesn't exist: {libpath}" ) - assert extension in pype.hosts.blender.plugin.VALID_EXTENSIONS, ( + assert extension in plugin.VALID_EXTENSIONS, ( f"Unsupported file: {libpath}" ) @@ -186,6 +188,7 @@ class BlendRigLoader(pype.hosts.blender.plugin.AssetLoader): collection_libpath = collection_metadata["libpath"] objects = collection_metadata["objects"] lib_container = collection_metadata["lib_container"] + obj_container = collection_metadata["obj_container"] normalized_collection_libpath = ( str(Path(bpy.path.abspath(collection_libpath)).resolve()) @@ -208,13 +211,14 @@ class BlendRigLoader(pype.hosts.blender.plugin.AssetLoader): action = armatures[0].animation_data.action - self._remove(objects, lib_container) + self._remove(objects, obj_container) - objects_list = self._process( + obj_container = self._process( str(libpath), lib_container, collection.name, action) # Save the list of objects in the metadata container - collection_metadata["objects"] = objects_list + collection_metadata["obj_container"] = obj_container + collection_metadata["objects"] = obj_container.all_objects collection_metadata["libpath"] = str(libpath) collection_metadata["representation"] = str(representation["_id"]) @@ -246,9 +250,9 @@ class BlendRigLoader(pype.hosts.blender.plugin.AssetLoader): collection_metadata = collection.get( blender.pipeline.AVALON_PROPERTY) objects = collection_metadata["objects"] - lib_container = collection_metadata["lib_container"] + obj_container = collection_metadata["obj_container"] - self._remove(objects, lib_container) + self._remove(objects, obj_container) bpy.data.collections.remove(collection)