From ca9abc83123339846831a11bc79aa084415ebd15 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 24 Oct 2017 10:03:20 +0200 Subject: [PATCH] Update Loaders to new-style plug-ins; inherit from `colorbleed.maya.plugin.ReferenceLoader`; fix updating referenced containers to also contain "new" nodes --- colorbleed/maya/plugin.py | 124 ++++++++++++++++++ .../plugins/maya/load/_load_animation.py | 10 +- colorbleed/plugins/maya/load/load_alembic.py | 33 +---- colorbleed/plugins/maya/load/load_look.py | 11 +- .../plugins/maya/load/load_mayaascii.py | 8 +- colorbleed/plugins/maya/load/load_model.py | 17 ++- colorbleed/plugins/maya/load/load_rig.py | 8 +- 7 files changed, 159 insertions(+), 52 deletions(-) create mode 100644 colorbleed/maya/plugin.py diff --git a/colorbleed/maya/plugin.py b/colorbleed/maya/plugin.py new file mode 100644 index 0000000000..2a7c32d2ac --- /dev/null +++ b/colorbleed/maya/plugin.py @@ -0,0 +1,124 @@ +from avalon import api + + +class ReferenceLoader(api.Loader): + """A basic ReferenceLoader for Maya + + This will implement the basic behavior for a loader to inherit from that + will containerize the reference and will implement the `remove` and + `update` logic. + + """ + def load(self, + context, + name=None, + namespace=None, + data=None): + + from avalon.maya import lib + from avalon.maya.pipeline import containerise + + asset = context['asset'] + + namespace = namespace or lib.unique_namespace( + asset["name"] + "_", + prefix="_" if asset["name"][0].isdigit() else "", + suffix="_", + ) + + self.process_reference(context=context, + name=name, + namespace=namespace, + data=data) + + # Only containerize if any nodes were loaded by the Loader + nodes = self[:] + if not nodes: + return + + return containerise( + name=name, + namespace=namespace, + nodes=nodes, + context=context, + loader=self.__class__.__name__) + + def process_reference(self, context, name, namespace, data): + """To be implemented by subclass""" + raise NotImplementedError("Must be implemented by subclass") + + def update(self, container, representation): + + import os + from maya import cmds + + node = container["objectName"] + + path = api.get_representation_path(representation) + + # Assume asset has been referenced + reference_node = next((node for node in cmds.sets(node, query=True) + if cmds.nodeType(node) == "reference"), None) + + file_type = { + "ma": "mayaAscii", + "mb": "mayaBinary", + "abc": "Alembic" + }.get(representation["name"]) + + assert file_type, "Unsupported representation: %s" % representation + + assert os.path.exists(path), "%s does not exist." % path + cmds.file(path, loadReference=reference_node, type=file_type) + + # TODO: Add all new nodes in the reference to the container + # Currently new nodes in an updated reference are not added to the + # container whereas actually they should be! + nodes = cmds.referenceQuery(reference_node, nodes=True, dagPath=True) + cmds.sets(nodes, forceElement=container['objectName']) + + # Update metadata + cmds.setAttr(container["objectName"] + ".representation", + str(representation["_id"]), + type="string") + + def remove(self, container): + """Remove an existing `container` from Maya scene + + Deprecated; this functionality is replaced by `api.remove()` + + Arguments: + container (avalon-core:container-1.0): Which container + to remove from scene. + + """ + + from maya import cmds + + node = container["objectName"] + + # Assume asset has been referenced + reference_node = next((node for node in cmds.sets(node, query=True) + if cmds.nodeType(node) == "reference"), None) + + assert reference_node, ("Imported container not supported; " + "container must be referenced.") + + self.log.info("Removing '%s' from Maya.." % container["name"]) + + namespace = cmds.referenceQuery(reference_node, namespace=True) + fname = cmds.referenceQuery(reference_node, filename=True) + cmds.file(fname, removeReference=True) + + try: + cmds.delete(node) + except ValueError: + # Already implicitly deleted by Maya upon removing reference + pass + + try: + # If container is not automatically cleaned up by May (issue #118) + cmds.namespace(removeNamespace=namespace, + deleteNamespaceContent=True) + except RuntimeError: + pass diff --git a/colorbleed/plugins/maya/load/_load_animation.py b/colorbleed/plugins/maya/load/_load_animation.py index cabb06d886..f4bcd6881d 100644 --- a/colorbleed/plugins/maya/load/_load_animation.py +++ b/colorbleed/plugins/maya/load/_load_animation.py @@ -1,7 +1,7 @@ -import avalon.maya.pipeline +import colorbleed.maya.plugin -class AbcLoader(avalon.maya.pipeline.ReferenceLoader): +class AbcLoader(colorbleed.maya.plugin.ReferenceLoader): """Specific loader of Alembic for the avalon.animation family""" families = ["colorbleed.animation", @@ -14,7 +14,7 @@ class AbcLoader(avalon.maya.pipeline.ReferenceLoader): icon = "code-fork" color = "orange" - def process(self, name, namespace, context, data): + def process_reference(self, context, name, namespace, data): import maya.cmds as cmds from avalon import maya @@ -43,4 +43,6 @@ class AbcLoader(avalon.maya.pipeline.ReferenceLoader): returnNewNodes=True) # load colorbleed ID attribute - self[:] = nodes \ No newline at end of file + self[:] = nodes + + return nodes diff --git a/colorbleed/plugins/maya/load/load_alembic.py b/colorbleed/plugins/maya/load/load_alembic.py index 4998e704b0..52ddde51c4 100644 --- a/colorbleed/plugins/maya/load/load_alembic.py +++ b/colorbleed/plugins/maya/load/load_alembic.py @@ -1,8 +1,7 @@ -from avalon import api -import avalon.maya.pipeline +import colorbleed.maya.plugin -class AbcLoader(avalon.maya.pipeline.ReferenceLoader): +class AbcLoader(colorbleed.maya.plugin.ReferenceLoader): """Specific loader of Alembic for the avalon.animation family""" families = ["colorbleed.animation", @@ -14,7 +13,7 @@ class AbcLoader(avalon.maya.pipeline.ReferenceLoader): icon = "code-fork" color = "orange" - def process(self, name, namespace, context, data): + def process_reference(self, context, name, namespace, data): import maya.cmds as cmds @@ -29,28 +28,4 @@ class AbcLoader(avalon.maya.pipeline.ReferenceLoader): self[:] = nodes - -# class SetDressAlembicLoader(avalon.maya.pipeline.ReferenceLoader): -# """Load the setdress as alembic""" -# -# families = ["colorbleed.setdress"] -# label = "Reference Alembic" -# representations = ["abc"] -# order = -10 -# icon = "code-fork" -# color = "orange" -# -# def process(self, name, namespace, context, data): -# -# import maya.cmds as cmds -# -# cmds.loadPlugin("AbcImport.mll", quiet=True) -# nodes = cmds.file(self.fname, -# namespace=namespace, -# sharedReferenceFile=False, -# groupReference=True, -# groupName="{}:{}".format(namespace, name), -# reference=True, -# returnNewNodes=True) -# -# self[:] = nodes + return nodes diff --git a/colorbleed/plugins/maya/load/load_look.py b/colorbleed/plugins/maya/load/load_look.py index 157bf89740..3260737349 100644 --- a/colorbleed/plugins/maya/load/load_look.py +++ b/colorbleed/plugins/maya/load/load_look.py @@ -1,10 +1,7 @@ -import os -import json - -import avalon.maya.pipeline +import colorbleed.maya.plugin -class LookLoader(avalon.maya.pipeline.ReferenceLoader): +class LookLoader(colorbleed.maya.plugin.ReferenceLoader): """Specific loader for lookdev""" families = ["colorbleed.look"] @@ -15,7 +12,7 @@ class LookLoader(avalon.maya.pipeline.ReferenceLoader): icon = "code-fork" color = "orange" - def process(self, name, namespace, context, data): + def process_reference(self, context, name, namespace, data): """ Load and try to ssign Lookdev to nodes based on relationship data Args: @@ -28,6 +25,8 @@ class LookLoader(avalon.maya.pipeline.ReferenceLoader): """ + import json + import os import maya.cmds as cmds from avalon import maya import colorbleed.maya.lib as lib diff --git a/colorbleed/plugins/maya/load/load_mayaascii.py b/colorbleed/plugins/maya/load/load_mayaascii.py index cdec04b773..07bf1ea836 100644 --- a/colorbleed/plugins/maya/load/load_mayaascii.py +++ b/colorbleed/plugins/maya/load/load_mayaascii.py @@ -1,7 +1,7 @@ -import avalon.maya.pipeline +import colorbleed.maya.plugin -class MayaAsciiLoader(avalon.maya.pipeline.ReferenceLoader): +class MayaAsciiLoader(colorbleed.maya.plugin.ReferenceLoader): """Load the model""" families = ["colorbleed.mayaAscii"] @@ -12,7 +12,7 @@ class MayaAsciiLoader(avalon.maya.pipeline.ReferenceLoader): icon = "code-fork" color = "orange" - def process(self, name, namespace, context, data): + def process_reference(self, context, name, namespace, data): import maya.cmds as cmds from avalon import maya @@ -26,3 +26,5 @@ class MayaAsciiLoader(avalon.maya.pipeline.ReferenceLoader): groupName="{}:{}".format(namespace, name)) self[:] = nodes + + return nodes diff --git a/colorbleed/plugins/maya/load/load_model.py b/colorbleed/plugins/maya/load/load_model.py index e5d9dd960a..0943eb4b24 100644 --- a/colorbleed/plugins/maya/load/load_model.py +++ b/colorbleed/plugins/maya/load/load_model.py @@ -1,8 +1,8 @@ -import avalon.maya.pipeline -import avalon.api +from avalon import api +import colorbleed.maya.plugin -class ModelLoader(avalon.maya.pipeline.ReferenceLoader): +class ModelLoader(colorbleed.maya.plugin.ReferenceLoader): """Load the model""" families = ["colorbleed.model"] @@ -13,7 +13,7 @@ class ModelLoader(avalon.maya.pipeline.ReferenceLoader): icon = "code-fork" color = "orange" - def process(self, name, namespace, context, data): + def process_reference(self, context, name, namespace, data): import maya.cmds as cmds from avalon import maya @@ -28,8 +28,10 @@ class ModelLoader(avalon.maya.pipeline.ReferenceLoader): self[:] = nodes + return nodes -class GpuCacheLoader(avalon.api.Loader): + +class GpuCacheLoader(api.Loader): """Load model Alembic as gpuCache""" families = ["colorbleed.model"] @@ -44,6 +46,7 @@ class GpuCacheLoader(avalon.api.Loader): import maya.cmds as cmds import avalon.maya.lib as lib + from avalon.maya.pipeline import containerise asset = context['asset']['name'] namespace = namespace or lib.unique_namespace( @@ -76,7 +79,7 @@ class GpuCacheLoader(avalon.api.Loader): nodes = [root, transform, cache] self[:] = nodes - return avalon.maya.pipeline.containerise( + return containerise( name=name, namespace=namespace, nodes=nodes, @@ -87,7 +90,7 @@ class GpuCacheLoader(avalon.api.Loader): import maya.cmds as cmds - path = avalon.api.get_representation_path(representation) + path = api.get_representation_path(representation) # Update the cache members = cmds.sets(container['objectName'], query=True) diff --git a/colorbleed/plugins/maya/load/load_rig.py b/colorbleed/plugins/maya/load/load_rig.py index 20df124274..96ff40fc26 100644 --- a/colorbleed/plugins/maya/load/load_rig.py +++ b/colorbleed/plugins/maya/load/load_rig.py @@ -2,11 +2,11 @@ import os from maya import cmds -import avalon.maya.pipeline from avalon import api, maya +import colorbleed.maya.plugin -class RigLoader(avalon.maya.pipeline.ReferenceLoader): +class RigLoader(colorbleed.maya.plugin.ReferenceLoader): """Specific loader for rigs This automatically creates an instance for animators upon load. @@ -21,7 +21,7 @@ class RigLoader(avalon.maya.pipeline.ReferenceLoader): icon = "code-fork" color = "orange" - def process(self, name, namespace, context, data): + def process_reference(self, context, name, namespace, data): nodes = cmds.file(self.fname, namespace=namespace, @@ -35,6 +35,8 @@ class RigLoader(avalon.maya.pipeline.ReferenceLoader): if data.get("post_process", True): self._post_process(name, namespace, context, data) + return nodes + def _post_process(self, name, namespace, context, data): # TODO(marcus): We are hardcoding the name "out_SET" here.