Goal
An idea from @mkolar (here) about providing the ability for developers to add custom fields for users to fill in during publishing. Most prominently, a comment field.
Implementation
Each filled in field is added to the context after Selection, but before Validation and are meant to get accessed either during Extraction of Validation.
I haven’t encountered an implementation before, but it seems rather common in web applications, apparently FTrack does something similar and possibly Shotgun too.
Ideally, I would like to see these fields added on a per-plugin basis. When a plug-in capable of making use of a comment should there be a commenting field, and if a plug-in is capable of making extensive use of fields, such as specifying start- and end-frames for e.g. a playblast or cache, I’d like fields to remain specific to this plug-in.
Perhaps this is a separate concern better handled separately?
Another question is, where do users fill in these fields?
Option A - Registration
User can add a file some place global with wanted fields, and register it at run-time.
pyblish.register_user_fields("//server/userfields.json")
fields.json
[
{
"label": "Comment",
"type": "text",
"name": "comment",
"value": "Write a comment about this publish",
}
]
This could work, though it doesn’t leave much room for adding fields to a specific plug-in, unless they are specified up-front.
{
"ValidateInstances": [{
"label": "Comment",
"type": "text",
"name": "comment",
"value": "Write a comment about this publish",
}],
"ExtractPlayblast": [{
"label": "Start frame",
"type": "number",
"range": [0, 1000]
}]
}
Alternatively, the data can be registered directly.
pyblish.register_user_fields([
{
"label": "Comment",
"type": "text",
"name": "comment",
"value": "Write a comment about this publish",
}
])
Option B - Embedded
Fields could be embedded into a plug-in.
As each plug-in is loaded up-front, the GUI have access to all of its properties before publishing.
class ValidateInstances(...):
fields = [
{
"label": "Comment",
"type": "text",
"name": "comment",
"value": "Write a comment about this publish",
}
]
The issue here is, what happens when two or more plug-ins define the same fields? As order is most often undefined, we can’t rely on a “last one wins” strategy.
Option C - Automatic
The above approach overlaps a previous issue, that we might be able to merge.
The thinking here is that, a developer would add arguments to his/her process_*
method and they would automagically appear as fields in the GUI.
def process_instance(self, instance, comment):
# comment is a user-field and gets added to the GUI
To know which widget to provide for, a type and description can be provided via the docstring; given it conforms with Google Napoleon or similar.
def process_instance(self, instance, comment):
"""Process this instance
Arguments:
comment (str): Provide a comment
"""
Another thing to consider is that these fields are specific to a GUI and have little to do with the plug-in itself, so adding them to the plug-in might not be the best approach for future-proofing and keeping responsibilities separate - e.g. we wouldn’t want these fields when using the plug-ins through another application, like a web application incapable of using them, or that needs similar fields for different purposes. Our plug-ins would become convoluted very quickly.
How else can we handle this? How does FTrack/Shotgun do it, is that a good/better way?