Example #1
0
    def _post_process_rig(self, name, namespace, context, options):

        output = next((node for node in self if node.endswith("out_SET")),
                      None)
        controls = next(
            (node for node in self if node.endswith("controls_SET")), None)

        assert output, "No out_SET in rig, this is a bug."
        assert controls, "No controls_SET in rig, this is a bug."

        # Find the roots amongst the loaded nodes
        roots = cmds.ls(self[:], assemblies=True, long=True)
        assert roots, "No root nodes in rig, this is a bug."

        asset = api.Session["AVALON_ASSET"]
        dependency = str(context["representation"]["_id"])

        self.log.info("Creating subset: {}".format(namespace))

        # Create the animation instance
        creator_plugin = get_creator_by_name(self.animation_creator_name)
        with maya.maintained_selection():
            cmds.select([output, controls] + roots, noExpand=True)
            api.create(creator_plugin,
                       name=namespace,
                       asset=asset,
                       options={"useSelection": True},
                       data={"dependencies": dependency})
Example #2
0
    def _post_process(self, name, namespace, context, data):

        # TODO(marcus): We are hardcoding the name "out_SET" here.
        #   Better register this keyword, so that it can be used
        #   elsewhere, such as in the Integrator plug-in,
        #   without duplication.

        output = next((node for node in self if node.endswith("out_SET")),
                      None)
        controls = next(
            (node for node in self if node.endswith("controls_SET")), None)

        assert output, "No out_SET in rig, this is a bug."
        assert controls, "No controls_SET in rig, this is a bug."

        # Find the roots amongst the loaded nodes
        roots = cmds.ls(self[:], assemblies=True, long=True)
        assert roots, "No root nodes in rig, this is a bug."

        asset = api.Session["AVALON_ASSET"]
        dependency = str(context["representation"]["_id"])

        # Create the animation instance
        with maya.maintained_selection():
            cmds.select([output, controls] + roots, noExpand=True)
            api.create(name=namespace,
                       asset=asset,
                       family="animation",
                       options={"useSelection": True},
                       data={"dependencies": dependency})
    def process(self, context, plugin):

        # Get the errored instances
        failed = []
        for result in context.data["results"]:
            if (result["error"] is not None and result["instance"] is not None
               and result["instance"] not in failed):
                failed.append(result["instance"])

        # Apply pyblish.logic to get the instances for the plug-in
        instances = pyblish.api.instances_by_plugin(failed, plugin)

        for instance in instances:
            data = toml.loads(instance[0]["avalon"].value())
            data["xpos"] = instance[0].xpos()
            data["ypos"] = instance[0].ypos()
            data["input"] = instance[0].input(0)
            data["publish"] = instance[0]["publish"].value()
            data["render"] = instance[0]["render"].value()
            data["render_farm"] = instance[0]["render_farm"].value()

            nuke.delete(instance[0])

            family = "render{}".format(os.environ["AVALON_TASK"].capitalize())
            api.create(data["subset"], data["asset"], family)
            node = nuke.toNode(data["subset"])
            node.setXYpos(data["xpos"], data["ypos"])
            node.setInput(0, data["input"])
            node["publish"].setValue(data["publish"])
            node["render"].setValue(data["render"])
            node["render_farm"].setValue(data["render_farm"])
Example #4
0
    def process_asset(self,
                      context: dict,
                      name: str,
                      namespace: Optional[str] = None,
                      options: Optional[Dict] = None):
        """
        Arguments:
            name: Use pre-defined name
            namespace: Use pre-defined namespace
            context: Full parenthood of representation to load
            options: Additional settings dictionary
        """
        libpath = self.fname
        asset = context["asset"]["name"]
        subset = context["subset"]["name"]
        lib_container = plugin.asset_name(asset, subset)
        unique_number = plugin.get_unique_number(asset, subset)
        namespace = namespace or f"{asset}_{unique_number}"
        container_name = plugin.asset_name(asset, subset, unique_number)

        layout_container = bpy.data.collections.new(container_name)
        blender.pipeline.containerise_existing(
            layout_container,
            name,
            namespace,
            context,
            self.__class__.__name__,
        )

        container_metadata = layout_container.get(
            blender.pipeline.AVALON_PROPERTY)

        container_metadata["libpath"] = libpath
        container_metadata["lib_container"] = lib_container

        # Create a setdress subset to contain all the animation for all
        # the rigs in the layout
        creator_plugin = get_creator_by_name(self.setdress_creator_name)
        if not creator_plugin:
            raise ValueError("Creator plugin \"{}\" was not found.".format(
                self.setdress_creator_name))
        parent = api.create(
            creator_plugin,
            name="animation",
            asset=api.Session["AVALON_ASSET"],
            options={"useSelection": True},
            data={"dependencies": str(context["representation"]["_id"])})

        layout_collection = self._process(
            libpath, layout_container, container_name,
            str(context["representation"]["_id"]), None, parent)

        container_metadata["obj_container"] = layout_collection

        # Save the list of objects in the metadata container
        container_metadata["objects"] = layout_collection.all_objects

        nodes = [layout_container]
        self[:] = nodes
        return nodes
Example #5
0
    def update(self, container: Dict, representation: Dict):
        """Update the loaded asset.

        This will remove all objects of the current collection, load the new
        ones and add them to the collection.
        If the objects of the collection are used in another collection they
        will not be removed, only unlinked. Normally this should not be the
        case though.
        """
        layout_container = bpy.data.collections.get(container["objectName"])
        if not layout_container:
            return False

        libpath = Path(api.get_representation_path(representation))
        extension = libpath.suffix.lower()

        self.log.info(
            "Container: %s\nRepresentation: %s",
            pformat(container, indent=2),
            pformat(representation, indent=2),
        )

        assert layout_container, (
            f"The asset is not loaded: {container['objectName']}")
        assert libpath, (
            "No existing library file found for {container['objectName']}")
        assert libpath.is_file(), (f"The file doesn't exist: {libpath}")
        assert extension in plugin.VALID_EXTENSIONS, (
            f"Unsupported file: {libpath}")

        layout_container_metadata = layout_container.get(
            blender.pipeline.AVALON_PROPERTY)
        collection_libpath = layout_container_metadata["libpath"]
        lib_container = layout_container_metadata["lib_container"]
        obj_container = plugin.get_local_collection_with_name(
            layout_container_metadata["obj_container"].name)
        objects = obj_container.all_objects

        container_name = obj_container.name

        normalized_collection_libpath = (str(
            Path(bpy.path.abspath(collection_libpath)).resolve()))
        normalized_libpath = (str(
            Path(bpy.path.abspath(str(libpath))).resolve()))
        self.log.debug(
            "normalized_collection_libpath:\n  %s\nnormalized_libpath:\n  %s",
            normalized_collection_libpath,
            normalized_libpath,
        )
        if normalized_collection_libpath == normalized_libpath:
            self.log.info("Library already loaded, not updating...")
            return

        actions = {}

        for obj in objects:
            if obj.type == 'ARMATURE':
                if obj.animation_data and obj.animation_data.action:
                    obj_cont_name = obj.get(
                        blender.pipeline.AVALON_PROPERTY).get('container_name')
                    obj_cont = plugin.get_local_collection_with_name(
                        obj_cont_name)
                    element_metadata = obj_cont.get(
                        blender.pipeline.AVALON_PROPERTY)
                    instance_name = element_metadata.get('instance_name')
                    actions[instance_name] = obj.animation_data.action

        self._remove(layout_container)

        bpy.data.collections.remove(obj_container)

        creator_plugin = get_creator_by_name(self.setdress_creator_name)
        if not creator_plugin:
            raise ValueError("Creator plugin \"{}\" was not found.".format(
                self.setdress_creator_name))

        parent = api.create(creator_plugin,
                            name="animation",
                            asset=api.Session["AVALON_ASSET"],
                            options={"useSelection": True},
                            data={"dependencies": str(representation["_id"])})

        layout_collection = self._process(libpath, layout_container,
                                          container_name,
                                          str(representation["_id"]), actions,
                                          parent)

        layout_container_metadata["obj_container"] = layout_collection
        layout_container_metadata["objects"] = layout_collection.all_objects
        layout_container_metadata["libpath"] = str(libpath)
        layout_container_metadata["representation"] = str(
            representation["_id"])
Example #6
0
    def _process(self, libpath, layout_container, container_name,
                 representation, actions, parent):
        with open(libpath, "r") as fp:
            data = json.load(fp)

        scene = bpy.context.scene
        layout_collection = bpy.data.collections.new(container_name)
        scene.collection.children.link(layout_collection)

        all_loaders = api.discover(api.Loader)

        avalon_container = bpy.data.collections.get(
            blender.pipeline.AVALON_CONTAINERS)

        for element in data:
            reference = element.get('reference')
            family = element.get('family')

            loaders = api.loaders_from_representation(all_loaders, reference)
            loader = self._get_loader(loaders, family)

            if not loader:
                continue

            instance_name = element.get('instance_name')

            element_container = api.load(loader,
                                         reference,
                                         namespace=instance_name)

            if not element_container:
                continue

            avalon_container.children.unlink(element_container)
            layout_container.children.link(element_container)

            element_metadata = element_container.get(
                blender.pipeline.AVALON_PROPERTY)

            # Unlink the object's collection from the scene collection and
            # link it in the layout collection
            element_collection = element_metadata.get('obj_container')
            scene.collection.children.unlink(element_collection)
            layout_collection.children.link(element_collection)

            objects = element_metadata.get('objects')
            element_metadata['instance_name'] = instance_name

            objects_to_transform = []

            creator_plugin = get_creator_by_name(self.animation_creator_name)
            if not creator_plugin:
                raise ValueError("Creator plugin \"{}\" was not found.".format(
                    self.animation_creator_name))

            if family == 'rig':
                for o in objects:
                    if o.type == 'ARMATURE':
                        objects_to_transform.append(o)
                        # Create an animation subset for each rig
                        o.select_set(True)
                        asset = api.Session["AVALON_ASSET"]
                        c = api.create(creator_plugin,
                                       name="animation_" +
                                       element_collection.name,
                                       asset=asset,
                                       options={"useSelection": True},
                                       data={"dependencies": representation})
                        scene.collection.children.unlink(c)
                        parent.children.link(c)
                        o.select_set(False)
                        break
            elif family == 'model':
                objects_to_transform = objects

            for o in objects_to_transform:
                self.set_transform(o, element.get('transform'))

                if actions:
                    if o.type == 'ARMATURE':
                        action = actions.get(instance_name, None)

                        if action:
                            if o.animation_data is None:
                                o.animation_data_create()
                            o.animation_data.action = action

        return layout_collection