diff --git a/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py b/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py index 43ab13cd79..6913e0836d 100644 --- a/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py +++ b/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py @@ -34,7 +34,6 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): # presets batch_extensions = ["edl", "xml", "psd"] - default_families = ["ftrack"] def process(self, context): # get json paths from os and load them @@ -213,10 +212,6 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): subset = in_data["subset"] # If instance data already contain families then use it instance_families = in_data.get("families") or [] - # Make sure default families are in instance - for default_family in self.default_families or []: - if default_family not in instance_families: - instance_families.append(default_family) instance = context.create_instance(subset) instance.data.update( diff --git a/openpype/hosts/standalonepublisher/plugins/publish/collect_instances.py b/openpype/hosts/standalonepublisher/plugins/publish/collect_instances.py index eb04217136..d753a3d9bb 100644 --- a/openpype/hosts/standalonepublisher/plugins/publish/collect_instances.py +++ b/openpype/hosts/standalonepublisher/plugins/publish/collect_instances.py @@ -16,12 +16,12 @@ class CollectInstances(pyblish.api.InstancePlugin): subsets = { "referenceMain": { "family": "review", - "families": ["clip", "ftrack"], + "families": ["clip"], "extensions": [".mp4"] }, "audioMain": { "family": "audio", - "families": ["clip", "ftrack"], + "families": ["clip"], "extensions": [".wav"], }, "shotMain": { diff --git a/openpype/hosts/standalonepublisher/plugins/publish/collect_matchmove.py b/openpype/hosts/standalonepublisher/plugins/publish/collect_matchmove.py deleted file mode 100644 index 5d9e8ddfb4..0000000000 --- a/openpype/hosts/standalonepublisher/plugins/publish/collect_matchmove.py +++ /dev/null @@ -1,29 +0,0 @@ -""" -Requires: - Nothing - -Provides: - Instance -""" - -import pyblish.api -import logging - - -log = logging.getLogger("collector") - - -class CollectMatchmovePublish(pyblish.api.InstancePlugin): - """ - Collector with only one reason for its existence - remove 'ftrack' - family implicitly added by Standalone Publisher - """ - - label = "Collect Matchmove - SA Publish" - order = pyblish.api.CollectorOrder - families = ["matchmove"] - hosts = ["standalonepublisher"] - - def process(self, instance): - if "ftrack" in instance.data["families"]: - instance.data["families"].remove("ftrack") diff --git a/openpype/modules/ftrack/plugins/publish/collect_ftrack_family.py b/openpype/modules/ftrack/plugins/publish/collect_ftrack_family.py index e6daed9a33..b505a429b5 100644 --- a/openpype/modules/ftrack/plugins/publish/collect_ftrack_family.py +++ b/openpype/modules/ftrack/plugins/publish/collect_ftrack_family.py @@ -1,29 +1,107 @@ +""" +Requires: + none + +Provides: + instance -> families ([]) +""" import pyblish.api +import avalon.api + +from openpype.lib.plugin_tools import filter_profiles -class CollectFtrackFamilies(pyblish.api.InstancePlugin): - """Collect family for ftrack publishing - - Add ftrack family to those instance that should be published to ftrack - +class CollectFtrackFamily(pyblish.api.InstancePlugin): """ + Adds explicitly 'ftrack' to families to upload instance to FTrack. - order = pyblish.api.CollectorOrder + 0.3 - label = 'Add ftrack family' - families = ["model", - "setdress", - "model", - "animation", - "look", - "rig", - "camera" - ] - hosts = ["maya"] + Uses selection by combination of hosts/families/tasks names via + profiles resolution. + + Triggered everywhere, checks instance against configured. + + Checks advanced filtering which works on 'families' not on main + 'family', as some variants dynamically resolves addition of ftrack + based on 'families' (editorial drives it by presence of 'review') + """ + label = "Collect Ftrack Family" + order = pyblish.api.CollectorOrder + 0.4998 + + profiles = None def process(self, instance): + if not self.profiles: + self.log.warning("No profiles present for adding Ftrack family") + return - # make ftrack publishable - if instance.data.get('families'): - instance.data['families'].append('ftrack') + task_name = instance.data.get("task", + avalon.api.Session["AVALON_TASK"]) + host_name = avalon.api.Session["AVALON_APP"] + family = instance.data["family"] + + filtering_criteria = { + "hosts": host_name, + "families": family, + "tasks": task_name + } + profile = filter_profiles(self.profiles, filtering_criteria, + logger=self.log) + + if profile: + families = instance.data.get("families") + add_ftrack_family = profile["add_ftrack_family"] + + additional_filters = profile.get("additional_filters") + if additional_filters: + add_ftrack_family = self._get_add_ftrack_f_from_addit_filters( + additional_filters, + families, + add_ftrack_family + ) + + if add_ftrack_family: + self.log.debug("Adding ftrack family for '{}'". + format(instance.data.get("family"))) + + if families and "ftrack" not in families: + instance.data["families"].append("ftrack") + else: + instance.data["families"] = ["ftrack"] else: - instance.data['families'] = ['ftrack'] + self.log.debug("Instance '{}' doesn't match any profile".format( + instance.data.get("family"))) + + def _get_add_ftrack_f_from_addit_filters(self, + additional_filters, + families, + add_ftrack_family): + """ + Compares additional filters - working on instance's families. + + Triggered for more detailed filtering when main family matches, + but content of 'families' actually matter. + (For example 'review' in 'families' should result in adding to + Ftrack) + + Args: + additional_filters (dict) - from Setting + families (list) - subfamilies + add_ftrack_family (bool) - add ftrack to families if True + """ + override_filter = None + override_filter_value = -1 + for additional_filter in additional_filters: + filter_families = set(additional_filter["families"]) + valid = filter_families <= set(families) # issubset + if not valid: + continue + + value = len(filter_families) + if value > override_filter_value: + override_filter = additional_filter + override_filter_value = value + + if override_filter: + add_ftrack_family = override_filter["add_ftrack_family"] + + return add_ftrack_family diff --git a/openpype/settings/defaults/project_settings/ftrack.json b/openpype/settings/defaults/project_settings/ftrack.json index b964ce07c3..03ecf024a6 100644 --- a/openpype/settings/defaults/project_settings/ftrack.json +++ b/openpype/settings/defaults/project_settings/ftrack.json @@ -200,6 +200,68 @@ } }, "publish": { + "CollectFtrackFamily": { + "enabled": true, + "profiles": [ + { + "hosts": [ + "standalonepublisher" + ], + "families": [], + "tasks": [], + "add_ftrack_family": true, + "advanced_filtering": [] + }, + { + "hosts": [ + "standalonepublisher" + ], + "families": [ + "matchmove", + "shot" + ], + "tasks": [], + "add_ftrack_family": false, + "advanced_filtering": [] + }, + { + "hosts": [ + "standalonepublisher" + ], + "families": [ + "review", + "plate" + ], + "tasks": [], + "add_ftrack_family": false, + "advanced_filtering": [ + { + "families": [ + "clip", + "review" + ], + "add_ftrack_family": true + } + ] + }, + { + "hosts": [ + "maya" + ], + "families": [ + "model", + "setdress", + "animation", + "look", + "rig", + "camera" + ], + "tasks": [], + "add_ftrack_family": true, + "advanced_filtering": [] + } + ] + }, "IntegrateFtrackNote": { "enabled": true, "note_with_intent_template": "{intent}: {comment}", diff --git a/openpype/settings/defaults/project_settings/standalonepublisher.json b/openpype/settings/defaults/project_settings/standalonepublisher.json index 7172612a74..443203951d 100644 --- a/openpype/settings/defaults/project_settings/standalonepublisher.json +++ b/openpype/settings/defaults/project_settings/standalonepublisher.json @@ -105,16 +105,23 @@ "label": "Render", "family": "render", "icon": "image", - "defaults": ["Animation", "Lighting", "Lookdev", "Compositing"], + "defaults": [ + "Animation", + "Lighting", + "Lookdev", + "Compositing" + ], "help": "Rendered images or video files" }, "create_mov_batch": { - "name": "mov_batch", - "label": "Batch Mov", - "family": "render_mov_batch", - "icon": "image", - "defaults": ["Main"], - "help": "Process multiple Mov files and publish them for layout and comp." + "name": "mov_batch", + "label": "Batch Mov", + "family": "render_mov_batch", + "icon": "image", + "defaults": [ + "Main" + ], + "help": "Process multiple Mov files and publish them for layout and comp." }, "__dynamic_keys_labels__": { "create_workfile": "Workfile", diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json index aae2bb2539..a94ebc8888 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json @@ -604,6 +604,82 @@ "key": "publish", "label": "Publish plugins", "children": [ + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "CollectFtrackFamily", + "label": "Collect Ftrack Family", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "collapsible": true, + "key": "profiles", + "label": "Profiles", + "use_label_wrap": true, + "object_type": { + "type": "dict", + "children": [ + { + "key": "hosts", + "label": "Host names", + "type": "list", + "object_type": "text" + }, + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + }, + { + "key": "tasks", + "label": "Task names", + "type": "list", + "object_type": "text" + }, + { + "type": "separator" + }, + { + "key": "add_ftrack_family", + "label": "Add Ftrack Family", + "type": "boolean" + }, + { + "type": "list", + "collapsible": true, + "key": "advanced_filtering", + "label": "Advanced adding if additional families present", + "use_label_wrap": true, + "object_type": { + "type": "dict", + "children": [ + { + "key": "families", + "label": "Additional Families", + "type": "list", + "object_type": "text" + }, + { + "key": "add_ftrack_family", + "label": "Add Ftrack Family", + "type": "boolean" + } + ] + } + } + ] + } + } + ] + }, { "type": "dict", "collapsible": true, diff --git a/website/docs/admin_hosts_aftereffects.md b/website/docs/admin_hosts_aftereffects.md index dc43820465..e3a09058da 100644 --- a/website/docs/admin_hosts_aftereffects.md +++ b/website/docs/admin_hosts_aftereffects.md @@ -14,7 +14,7 @@ All of them are Project based, eg. each project could have different configurati Location: Settings > Project > AfterEffects -![Harmony Project Settings](assets/admin_hosts_aftereffects_settings.png) +![AfterEffects Project Settings](assets/admin_hosts_aftereffects_settings.png) ## Publish plugins diff --git a/website/docs/assets/ftrack/ftrack-collect-advanced.png b/website/docs/assets/ftrack/ftrack-collect-advanced.png new file mode 100644 index 0000000000..5249685c86 Binary files /dev/null and b/website/docs/assets/ftrack/ftrack-collect-advanced.png differ diff --git a/website/docs/assets/ftrack/ftrack-collect-main.png b/website/docs/assets/ftrack/ftrack-collect-main.png new file mode 100644 index 0000000000..7c75cd6269 Binary files /dev/null and b/website/docs/assets/ftrack/ftrack-collect-main.png differ diff --git a/website/docs/module_ftrack.md b/website/docs/module_ftrack.md index bd0dbaef4f..c3b9fd6bc2 100644 --- a/website/docs/module_ftrack.md +++ b/website/docs/module_ftrack.md @@ -196,7 +196,7 @@ Is used to remove value from `Avalon/Mongo Id` Custom Attribute when entity is c ### Sync status from Task to Parent -List of parent boject types where this is triggered ("Shot", "Asset build", etc. Skipped if it is empty) +List of parent object types where this is triggered ("Shot", "Asset build", etc. Skipped if it is empty) ### Sync status from Version to Task @@ -214,3 +214,29 @@ This is usefull for example if first version publish doesn't contain any actual ### Update status on next task Change status on next task by task types order when task status state changed to "Done". All tasks with the same Task mapping of next task status changes From → To. Some status can be ignored. + +## Publish plugins + +### Collect Ftrack Family + +Reviews uploads to Ftrack could be configured by combination of hosts, families and task names. +(Currently implemented only in Standalone Publisher, Maya.) + +#### Profiles + +Profiles are used to select when to add Ftrack family to the instance. One or multiple profiles could be configured, Families, Task names (regex available), Host names combination is needed. + +Eg. If I want review created and uploaded to Ftrack for render published from Maya , setting is: + +Host names: 'Maya' +Families: 'render' +Add Ftrack Family: enabled + +![Collect Ftrack Family](assets/ftrack/ftrack-collect-main.png) + +#### Advanced adding if additional families present + +In special cases adding 'ftrack' based on main family ('Families' set higher) is not enough. +(For example upload to Ftrack for 'plate' main family should only happen if 'review' is contained in instance 'families', not added in other cases. ) + +![Collect Ftrack Family](assets/ftrack/ftrack-collect-advanced.png) \ No newline at end of file