Instance argument for Actions

Dependency injection was deprecated from 1.3 onwards in favour of explicit plug-ins - ContextPlugin and InstancePlugin.

For this to work, we could potentially make it ContextAction and InstanceAction.

1 Like

You are right, thought there was something I was missing:)

+1

Makes sense to me. :thumbsup:

Feel free to make it a feature issue, should be fairly straightforward to implement.

In theory would an InstanceAction be executable from an instance as well? Ei. right-click on an instance, and select the action.

Not sure about that. :slight_smile: How would you associate this action with the Instance?

And if you were doing something like this…

instance.append(MyAction)

What would it mean for it to be a ContextAction or InstanceAction? Mind blown?

Sorry, thought I could hit two bird with one stone. Was thinking towards the Importer

This is where instance actions could come in, but the logic for having an action on an instance would be different than an action on a plugin iterating over instances. Is that right, @marcus?

I don’t know, there are probably more than one way of going at it. Feel free to propose your ideas. Maybe start with a few examples of actions you would expect to find on an instance?

First would probably be a select action:

class SelectInstance(pyblish.api.InstanceAction):

    label = 'Select'
    on = 'all'

    def process(self, instance):

        pymel.core.select(instance[0])

You would assign the action when collecting the instance:

class CollectLocators(pyblish.api.ContextPlugin):

    order = pyblish.api.CollectorOrder

    def process(self, context):

        for node in pymel.core.ls(type='locator'):
            instance = context.add_instance(node.name(), family='locator')
            instance.actions.append(SelectInstance)

That looks great, I think.

It also might make sense that it is an InstanceAction, in which instance in the argument signature is the right-clicked instance in the view. A ContextAction could take context, and pretty much still make sense, right?

The assignment also works for me.

I think let’s mock it up. It’d need the ContextAction and InstanceAction classes in pyblish-base, to be formatted in pyblish-rpc and finally drawn in pyblish-qml. There is already actions in each project to use for reference and in all should be quite straightforward to implement.

Does it make sense as well that if an InstanceAction assigned to an instance is run once, and an InstanceAction assigned to a plugin will potentially be run multiple times?

Spontaneously, yes I think it does. :slight_smile:

Referencing the original issue for completeness.

Slight adjustment to @BigRoy code, since the context returns None.

# pseudocode
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:
            failed.append(result["instance"])

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

If an Action is only available on failed would this also be a problem? I’m assuming it wouldn’t be because it’ll only fail with errors.

# pseudocode
class MyAction(pyblish.api.Action):
    on = "failed"

Doesn’t seem to be a problem :smile:

A problem how?

The result["error"] or result["instance"] being None.

I just pulled the latest repos to test Action icons and indeed found these returning None. It’s strange that before it did actually work and run through the code. Was it ignoring the context maybe? Anyway, thanks @tokejepsen, checking for None works as expected.

1 Like

Were they returning None even when there was an error, you mean? If you can post a reproducible, that would be perfect.

Yes, well… the others (other instances) returned None. Say you run an Action and have two instances. One of them fails, the other succeeds. Because the first failed the Action becomes available. If you run the Action then the other instance will still be iterated and would have result["error"] is None so you’d have to ensure you’re catching that.

Similarly in any Action the result["instance"] is None at least once because of the “Context” being iterated (if I understood @tokejepsen correctly). I think this is new behavior since I can’t recall having that problem before.

Does that help?