def process(self, instance):

        variant = instance.data["subset"][len("animation"):].lower()
        members = instance[:]

        # Re-Create instances
        context = instance.context
        context.remove(instance)
        source_data = instance.data

        ANIM_SET = "ControlSet"
        out_cache = dict()

        if variant == "default":
            # Collect animatable nodes from ControlSet of loaded subset
            out_sets = list()

            for node in cmds.ls(members, type="transform", long=True):
                try:
                    container = pipeline.get_container_from_group(node)
                except AssertionError:
                    continue

                sets = cmds.ls(cmds.sets(container, query=True),
                               type="objectSet")
                out_sets += [s for s in sets if s.endswith(ANIM_SET)]

            for node in out_sets:
                name = node.rsplit(":", 1)[-1][:-len(ANIM_SET)] or "Default"
                self.log.info(name)
                namespace = lib.get_ns(node)
                animatables = cmds.ls(cmds.sets(node, query=True), long=True)

                out_cache[namespace] = (name, animatables)

        else:
            # Collect animatable nodes from instance member
            for node in cmds.ls(members, type="transform", long=True):
                namespace = lib.get_ns(node)
                try:
                    # Must be containerized
                    pipeline.get_container_from_namespace(namespace)
                except RuntimeError:
                    continue

                if namespace not in out_cache:
                    out_cache[namespace] = (variant, list())
                out_cache[namespace][1].append(node)

        for namespace, (name, animatables) in out_cache.items():
            instance = context.create_instance(namespace or name)
            container = pipeline.get_container_from_namespace(namespace)
            asset_id = cmds.getAttr(container + ".assetId")

            namespace = namespace[1:]  # Remove root ":"

            instance.data.update(source_data)
            instance.data["subset"] = ".".join(["animation", namespace, name])
            instance[:] = animatables
            instance.data["outAnim"] = animatables
            instance.data["animatedNamespace"] = namespace
            instance.data["animatedAssetId"] = asset_id
            # (NOTE) Although we put those animatable nodes to validate
            #        AvalonUUID existence, but currently AvalonUUID is
            #        not needed on load.
            instance.data["requireAvalonUUID"] = animatables
示例#2
0
    def process_import(self, context, name, namespace, group, options):
        from maya import cmds, mel
        from reveries import plugins

        representation = context["representation"]
        asset_id = representation["data"]["animatedAssetId"]
        selected = cmds.ls(selection=True, long=True)

        # Collect namespace from selected nodes
        namespaces = defaultdict(set)
        for node in selected:
            ns = lib.get_ns(node)
            if ns == ":":
                continue
            namespaces[ns].add(node)

        for ns, nodes in namespaces.items():
            try:
                container = pipeline.get_container_from_namespace(ns)
            except RuntimeError:
                continue

            if asset_id != cmds.getAttr(container + ".assetId"):
                confirm = plugins.message_box_warning(
                    "Warning",
                    "Applying animation to different asset, are you sure ?",
                    optional=True,
                )
                if not confirm:
                    raise Exception("Operation canceled.")

            target_ns = ns
            members = nodes
            break

        else:
            raise Exception("No matched asset found.")

        cmds.loadPlugin("animImportExport", quiet=True)

        entry_path = self.file_path(representation).replace("\\", "/")
        sele_path = entry_path.rsplit("anim", 1)[0] + "mel"
        sele_path = os.path.expandvars(sele_path)

        with capsule.maintained_selection():
            # Select nodes with order
            with contextlib.nested(capsule.namespaced(target_ns, new=False),
                                   capsule.relative_namespaced()):
                self._selection_patch(sele_path)
                mel.eval("source \"%s\"" % sele_path)

            targets = cmds.ls(selection=True, long=True)
            nodes = cmds.file(entry_path,
                              force=True,
                              type="animImport",
                              i=True,
                              importTimeRange="keep",
                              ignoreVersion=True,
                              returnNewNodes=True,
                              options=("targetTime=4;"
                                       "option=replace;"
                                       "connect=0"))
            # Apply namespace by ourselves, since animImport does not
            # take -namespace flag
            namespaced_nodes = list()
            for node in nodes:
                node = cmds.rename(node, namespace + ":" + node)
                namespaced_nodes.append(node)

            # Delete not connected
            targets = set(targets)
            connected = list()
            for node in namespaced_nodes:
                future = cmds.listHistory(node, future=True)
                future = set(cmds.ls(future, long=True))
                if targets.intersection(future):
                    connected.append(node)
                else:
                    cmds.delete(node)

            if not connected:
                raise Exception("No animation been applied.")

            self[:] = connected

        # Remove assigned from selection
        unprocessed = list(set(selected) - members)
        cmds.select(unprocessed, replace=True, noExpand=True)
示例#3
0
    def process(self, instance):
        import maya.cmds as cmds
        from reveries.maya import lib, pipeline

        variant = instance.data["subset"][len("animation"):].lower()
        members = instance[:]

        # Re-Create instances
        context = instance.context
        context.remove(instance)
        source_data = instance.data

        ANIM_SET = "ControlSet"
        out_cache = dict()

        if variant == "default":
            # Collect animatable nodes from ControlSet of loaded subset
            out_sets = list()

            for node in cmds.ls(members, type="transform"):
                try:
                    # Must be containerized subset group node
                    pipeline.get_container_from_group(node)
                except AssertionError:
                    continue

                namespace = lib.get_ns(node)
                out_sets += cmds.ls("%s:*%s" % (namespace, ANIM_SET),
                                    sets=True)

            for node in out_sets:
                name = node.rsplit(":", 1)[-1][:-len(ANIM_SET)] or "Default"
                namespace = lib.get_ns(node)
                animatables = cmds.ls(cmds.sets(node, query=True),
                                      type="transform")

                key = (namespace, name)
                self.log.info("%s, %s" % key)
                if not animatables:
                    self.log.warning("No animatable (e.g. controllers) been "
                                     "found in '%s', skipping.." % node)
                    continue

                out_cache[key] = animatables

        else:
            # Collect animatable nodes from instance member
            for node in cmds.ls(members, type="transform"):
                namespace = lib.get_ns(node)
                try:
                    # Must be containerized
                    pipeline.get_container_from_namespace(namespace)
                except RuntimeError:
                    continue

                key = (namespace, variant)

                if key not in out_cache:
                    self.log.info("%s, %s" % key)
                    out_cache[key] = list()

                out_cache[key].append(node)

        for (namespace, name), animatables in sorted(out_cache.items()):
            container = pipeline.get_container_from_namespace(namespace)
            asset_id = cmds.getAttr(container + ".assetId")

            fixed_namespace = namespace[1:]  # Remove root ":"
            # For filesystem, remove other ":" if the namespace is nested
            fixed_namespace = fixed_namespace.replace(":", "._.")

            subset = ".".join(["animation", fixed_namespace, name])

            instance = context.create_instance(subset)
            instance.data.update(source_data)
            instance.data["subset"] = subset
            instance[:] = animatables
            instance.data["outAnim"] = animatables
            instance.data["animatedNamespace"] = namespace
            instance.data["animatedAssetId"] = asset_id
            # (NOTE) Although we put those animatable nodes to validate
            #        AvalonUUID existence, but currently AvalonUUID is
            #        not needed on load.
            instance.data["requireAvalonUUID"] = animatables