Custom UI prototype

Hi everyone,

As I’ve mentioned in other threads, we (ftrack) are working a brand new publish UI for our integrations, and we’re experimenting on using Pyblish for this.

I’ve been asking questions about pyblish both on the forum ( Filtering collected instances based on category/family
and Selecting instances
) as well as sharing some information privately.

First of all some background on our goals:

  • Provide a consistent publish experience across applications and departments (as far as possible). We think that pyblish can be an important part of this.
  • Make an approachable UI that is easy for the artist to understand and use. This means that we don’t want to overwhelm them with options and information that is not relevant.
  • Should work out-of-the-box and not requiring any technical expertise to setup. So very low configuration requirements to get started. This has some implications on what we can and cannot do. E.g. we cannot guarantee that there will be a certain task type, or asset type in ftrack - and as far as possible we would like to be agnostic to this.
  • Under the hood it must be powerful and extensible for our fellow developers. Studios works differently and we must allow a lot of customisation. This is also where we hope pyblish plugin capabilities will shine :slight_smile:

With these goals in mind I’ve written a prototype / technical preview of how our publish tools could work. It does not reflect final thoughts and design, but should hint on what we’re considering workflow-wise. Here is a video of the interface: video for download

And here is a screenshot:

A few things I would like to point out in this video:

A) The initial dialog let’s the user decide what they would like to publish. In the video there are two options: Camera and Custom. The registration of these works like a traditional (synchronous) ftrack Action and when launched the UI is opened as:

   dialog = ftrack_pyblish_maya_prototype.pyblish_ui.PublishDialog(
        label='Camera',
        description=(
            'from here you can select and publish Maya cameras to ftrack.'
        ),
        instance_filter=(
            lambda instance: instance.data.get('family') in ('camera',)
        )
    )

As you can see the dialog is opened with a filter that only let’s the user pick from a defined set of instances. The Custom action will not filter instances at all, so artists can pick any combination they want.

B) The publish dialog will show you all valid instances for your selected publish action. Instances will be grouped on family.

When selecting an instance we set a publish boolean in the instance.data. From
Filtering collected instances based on category/family I understand that this is debated and that it is recommended to persist this into the scene. It is still something we’re discussing and maybe something that can be left to the Studio to decide (see #4 in the goals).

C) When an instance is selected we’re also displaying a set of options for the instance. In the current implementation the options are provided by the instance plugins with a matching family above Collector order.

The options that I’ve implemented are based on the ftrack action UI specification: http://ftrack.rtd.ftrack.com/en/stable/developing/actions.html. I’m aware that these are probably too basic and that many situations will require a lot more control. This is something we’re still researching, but I want to get this out here so that we can discuss the overall approach.

Again, I assume this to be a rather hot topic. Based on the discussions of selecting instances I guess that many of you will want this information to be persisted into the scene so that subsequent publishes will work the same. And also if you would do the publish on another machine the same scene + pyblish plugins would produce the same result. I’m not sure what path we will take here but I’m interested in your thoughts.

Here is some code that I’ve been experimenting with - not in any way a final design but you can see my intentions:

class ExtractMayaCamera(pyblish.api.InstancePlugin):
    '''Extract maya cameras from scene.'''

    order = pyblish.api.ExtractorOrder

    families = ['camera']

    def process(self, instance):
        '''Process *instance* and extract maya camera.'''
        if instance.data.get('publish'):
            print (
                'Extracting camera using options:',
                instance.data.get('options')
            )

ExtractMayaCamera.__ftrack_options = [{
    'type': 'boolean',
    'label': 'Bake camera',
    'name': 'bake_camera'
}, {
    'type': 'boolean',
    'label': 'Lock camera',
    'name': 'lock_camera'
}, {
    'type': 'number',
    'label': 'Start frame',
    'name': 'start_frame_camera'
}, {
    'type': 'number',
    'label': 'End frame',
    'name': 'end_frame_camera'
}]

When an option is modified it is saved in dictionary instance.data[‘options’] so that it is available when processing.

D) On the bottom right corner there is a "Publish options” section. These are options gathered from plugins above Collector order that runs on the Context. It works the same way as for instance plugins but when an option is modified it is saved in dictionary context.data[‘options’] so that it is available when processing.

~

I’ve added a bitbucket repo with the prototype code. I want to point out that this is a prototype that focuses on how our pyblished based publish tool could work. So try not to judge me on code quality or architecture :wink:

Anyhow, here is the repository if you want to browse the code: https://bitbucket.org/ftrack/ftrack-pyblish-prototype/overview. It is not a public repo so ping me here or privately with your bitbucket account name and I will let you in.

Do I have to say that I’m awaiting your feedback? :slight_smile:

1 Like

This is looking great:) I like where it is all going.

For a non-intrusive persistance, you could save the publish state as meta data in the scene files. This can be done with “callbacks” in Pyblish.
You are right though, that this should be overridable for studios to set down their own workflow.

1 Like

Exactly this was one of my main points I’d raise. This mockup UI seems like an “export selected” kind of workflow. Select cameras that are available and let them pick at that time how that output should go. At our studio we currently use a new workflow that we’ve come to love where the contents of the scene remain tagged. An animator for example can continue tweaking his shot and publish later with the previous setting. Basically we have a form of persistent instances in the scene that would get picked up by Pyblish using its collectors.

Whenever an artist wants to define a new publish “instance” they would create that instance (make the persistent data) and then proceed to publish afterwards.

At what point is this interface about to be used? Is this after it would’ve been tagged and gets collected by Pyblish?


I’m a bit busy at the moment. But I’ll try to do some more analysis on this UI and join the discussion. Either way, great initiative! :smiley:

At the moment I collect instances when you open the second “Publish dialog” where all the options are.

My intention is that the UI should reflect what has been collected. So if you have set instance.data[‘publish’] to be True in one of the collectors, it will be ticked in the UI. If you have set instance[‘options’][‘bake_camera’] = True, it will also be reflected in the UI.

:+1:

I like it…a lot. Certainly a right direction so far. I have a few comments though.

Absolutely agree. However, from this test, it’s on the borderline of feeling like there is some magic happening behind the scenes (and there is of course). One thing we use literally constantly is optional extractors. If I’m publishing a camera, by default it goes out as alembic, but I can toggle export as fbx and ma too. Each of these is it’s own extractor of course. The same goes for geometry, default might be alembic, but we often need fbx, obj, ma too. This workflow proved very powerful to us combined with ftrack components.

What you have there right now pretty much only shows instances and options. I think the an area, showing any optional plugins that user can turn on, would make this spot on.

We discussed similar design here previously, and the mockup image is pretty much what you have here, plus the optional plugins.

I can imagine the optional section could be collapsed by default, or be a kind of rollout on each instance (being able to check plugins per instane), or anything similar.

Long story short…You may have skimmed it a hair too thin :slight_smile:

1 Like

True. Though as far as there is the ‘custom’ option, I’d assume that your workflow could easily work with that. I can’t see ourselves going back to selective publishing either after almost 2 year with bulk publishing.

1 Like

Yes! I didn’t have the time to work this in but having extractors optional and showing up is coming!

I was influenced by this when making my sketches and this prototype.

Yepp, this is our intention. If you want everything you have it under “Custom”, and as I showed in my code sample it is very little difference.

I thought this would be left up to the options?

If you wanted an alembic export, there would an alembic option to enable on the instance. The point being that the user don’t need to know about what a plugin is, and just choose the publish options.

Yes correct, I imagine it being part of the options UI and an ordirnary user would not know about the underlying plugins

Great that will work well. The only thing I can think of a a trouble is bulk toggles. I just had a scene with 20 characters (each as an instance), ticking and unticking smal boxes for all of them will be a massive paint, not to mention there could easily be a scene with 100+ instances.

Maybe having the ‘family’ section somehow selectable and whatever option I set on that, reflect to all the instances under it. That would make it possibly to work really quickly with big scenes and do small overrides on certain instances if needed.

1 Like

To be more precise I’m considering using the optional and active options on the plugin. This would also toggle the corresponding plugin options section (if there are any options). I will try to update the prototype to reflect this

Good point!

Thanks for sharing @mattiaslagergren!

Before I add my comments, would it be possible to get an estimate on what audience you are targeting?

For example, are you expecting indie companies of 1-4 to be using this, and/or large corporations such as MPC? Who, if anyone, is expected to aid in development and push the technology and user experience further? Are @tokejepsen and @mkolar part of this userbase?

These decisions might influence both the implementation, design and UX of this project and the comments I would make.

To get a feel for this, have a look at any of the recent versions of pyblish-qml. @tokejepsen implemented this a while back.

Hey @marcus, I’m looking forward to your feedback!

First of all I would like to point out something that I forgot in my first post: We would like our tools to stay within the “Pyblish realm” as much as possible. This means that I would like us to avoid doing anything that goes fundamentally against “the pyblish way”.

This way I hope that we can see a growing ftrack / pyblish ecosystem where our users can share Pyblish plugins with each other.

I think there are a few things that I’d like us to achieve that ties in to our goals in my original post:

  1. It should work out-of-the-box with low configuration for companies that does not have any technical expertise. Here we provide a basic toolset (UI/Framework + pyblish plugins) that can be extended by downloading packages from the ftrack / pyblish ecosystem.
  2. More tech-savvy companies that have a developer and more pipeline experience could extend our tools with their own ftrack / pyblish plugins. People would add validators, integrators, changing how extractors work, disable plugins that they are not using, etc. My goal here is to allow as much flexibility as possible without users having to fork our code-base - i.e. they should still be able use our UI/Framework. This is also where I expect pyblish will shine and I hope we can see an active and growing ftrack/pyblish Community where developers are contributing back with extensions and packages.
  3. For companies that already have lot’s of developers and want to write their own tools, I can see some of them adopting parts of our tools. Perhaps forking/modifying source, using bits and pieces and so on.

Speaking in terms of sizes I would expect small-size companies to be tending towards #1, and larger towards #3 - but with lot’s of variations.

Ok, that’s great. There are a few best practices developed so far, but in general I think the space is large enough and framework open enough for individuality and exploration. A GUI such as this I think is a great addition to what is being explored, especially as it contrasts the other GUIs in both simplicity (i.e. the front page) and customisability (i.e. the option to edit data interactively).

The scene persistence I think is a good idea, an option, but not necessarily essential to still being in the Pyblish realm.

Ok, based on this, I would like to make a suggestion:

Rather than try and make 1 product fit for all, you make 2 fit for each extreme.

I think that sounds like twice the amount of work, but that in reality it will save you time, increase adoption and produce a better result all around. The reason being that I can see each extreme asking for opposing features - e.g. more control, less complexity, more customisability, easier setup.

For example, you could make one “industrial” and one “fluffy”. Smaller/starter teams take on the fluffy interface/workflow (similar to this prototype), whereas larger teams like The Mill take on the industrial version. This way you can appeal to each extreme, without making sacrifices on either and try to make everyone happy all at once.

I might even go as far as to suggest the “fluffy” version be your free, open source offering - to give your userbase a taste of publishing - whereas the “industrial” is considered the next level, with more control, diagnostics, customisability and what not. Though I also think sticking with open source would further adoption and produce the best result in the end, taking into account the fact that a paid version would enable you to dedicate funds internally on its development.

Thank you @marcus, this was encouraging to hear!

About industrial vs fluffy; we will probably start with a fluffy version and try to keep things open and extensible. In the end there may even be a bigger player that wants to fork/build an industrial version. Or, maybe a 3rd party integrator that could drive this and perhaps even sell it as a paid add-on.

Thumbs Up.

Apart from that. I do apologize for the unavoidable…

This is the user reaction I’ll be hoping for from our artists, once this is live.

Sometimes one simply can’t resist.

1 Like

Shortly after replying this I realised that I didn’t really think things through. The settings are per instance, where as making a plugin active is a per-plugin setting. So simply rendering “Enable alembic (extractor)” as part of the instance settings won’t work.

This lead to a discussion here about per-instance vs per-plugin settings. I thought I’d summarise what has been said in this thread, and share my pros and cons with you, and see if you have any feedback:

(+) Settings per instance gives a lot of freedom to decide if how one of the instances that you’re publishing is integrated/extracted.
(-) The concepts of making a plugin active maps better to per-plugin settings. To mitigate this we could still allow a separate section to disable/enable plugins - as proposed by @mkolar above.
(-) Bulk editing is easier with per-plugin based settings. However, this may be just about making a good UI bulk editing feature.

Anything else you can think of? I’m leaning towards per-instance since that gives the most freedom.

I would go with per-instance setting as a foundation. As you said, bulk editing, could simply be a matter of UI design.