[solved] Grouping instances base on their family

hey guys

i created two plugins and i see an interesting thing, two family with one name in the list of instances:
collect_rig.py

import pyblish.api
from maya import cmds


class CollectRig(pyblish.api.Collector):
    """Discover and collect available rigs into the context"""
    hosts = ["maya"]  # Only compatible with Maya

    def process(self, context):
        for node in cmds.ls(sets=True):
            if not node.endswith("_RIG"):
                continue

            name = node.rsplit("_", 1)[0]
            instance = context.create_instance(name, family="rig")

            # Collect associated nodes
            members = cmds.sets(node, query=True)
            cmds.select([node] + members, noExpand=True)
            instance[:] = cmds.file(
                constructionHistory=True,
                exportSelected=True,
                preview=True,
                force=True)

collect_rig_instance.py

import pyblish.api
from maya import cmds


class SelectRigInstance(pyblish.api.Selector):
    hosts = ["maya"]  # Only compatible with Maya

    def process(self, context):
        instance = context.create_instance(name="RigInstance")
        # instance.set_data("family", "rig")  
        instance.data["family"] = "rig"

        for node in cmds.ls():
            instance.add(node)

Differences

  • pyblish.api.Collector
  • pyblish.api.Selector

and

  • instance = context.create_instance(name, family=“rig”)
  • instance = context.create_instance(name=“RigInstance”)
    instance.data[“family”] = “rig”

Problem
set1 is a set named set1_RIG

Two family with same name

i’m using Pyblish Version 1.2.2

thanks

What’s the problem?

There seems to be a screenshot now in the updated post. He’s referring to the double family rig instead of having a single one with both instances.

i changed Selector to Collector, but does not changed anymore

Ah, that’s because they are shown in the order they are run, and they are run in the order you added them, unless you sort them afterwards.

Try this in the last-to-run collector.

context.create_instance(name, family="rig")
context[:] = sorted(context, key=lambda i: i.data["family"])

It will sort instances by their family.

To more easily find this thread while searching, I’ll throw in some additional keywords; duplicate families in gui, multiple section labels, sorting the context.

1 Like

thanks marcus
i added the code to both plugins and it works

just i like to know what is contect[:] and it means i saw many things like that, like asset[:]

thanks again

That actually does make sense!

Actually you don’t want to put this in every plug-in. Just make a new SortCollector plug-in that runs last like order +0.1.

You’re using the python syntax for in-place list assignment with the context to override the data in the object itself.

context = [1, 2, 3]

This would make a new object and assign it to the context variable in the local space. The “new” assignment is important here, because that’s what the other one does different.

context[:] = [1, 2, 3]

Here the context object is still the same object in memory as opposed to instantiating a new object and using that. As such the contents of context are altered as opposed to assigning a new object purely to the name.

It’s more of a Python thing than a Pyblish thing. Just imagine you’re updating the context’ data so that it is sorted.

But i thought to this point that we should take two things in our consideration:

  1. all similar family instances categorized automatically under one name
  2. duplicate plugins ignored (based on something)

that i think second is applying now.

make sense?

This might be helpful: [solved] Collection sorting

It will sort the instances by family and name, so you get a completely alphabetised list of instances.

Pyblish tries to do it for you, but prioritizes being clear on the order of processing the plug-ins.

They are actually combined (visually under a header) only when “processed one after the other”. Since Pyblish’ order of processing for plug-ins is dependent of the order they are added in the context.

In your scenario you have two collectors collecting instances of family rig that run with the same order as other plug-ins. The same order means it’s somewhat undefined which must run first or last and as such no specific order is assumed. This means your two rigging collectors might not run right after each other, another collector could be running in-between. That’s exactly what’s happening.

You’re collecting:

  • set1 (rig)
  • MyInstance (default)
  • Maya_Instance (animate)
  • RigInstance (rig)

And this is stored in the context (as a list).
So you would have (somewhat simplified example here):

context = ['set1', 'MyInstance', 'Maya_Instance', 'RigInstance']

In this order even though set1 and RigInstance are both of family rig they cannot be grouped together because they don’t run one after the other. So @marcus solution is to “sort” the instances by family so they can always be grouped together.

Basically it is you taking control and telling it the order you prefer.

Theoretically you can sort it in any way you like and take full control over the order of the plug-ins if you need to. Again it’s something that Pyblish doesn’t try to make too much assumptions about.

Also see @tokejepsen link:


I think this only happens with Plug-ins that conflict by the name of the class.

Thanks you @tokejepsen
so if we use order = pyblish.api.Collector.order + 0.2 we don’t need to use context[:] = sorted(context, key=lambda i: i.data["family"])
yes?

You will need to sort the context in any case if you want the instances alphabetised.

1 Like

Thanks @BigRoy
yes, i see it with just this line order = pyblish.api.Collector.order + 0.1