From 00f2e16dca2cb37a53a4a6b3096c0f11142a9b66 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sun, 26 Feb 2023 10:23:39 +0000 Subject: [PATCH 01/59] Static implementation. --- openpype/hosts/maya/plugins/publish/collect_review.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index eb872c2935..c76d4bae97 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -139,3 +139,13 @@ class CollectReview(pyblish.api.InstancePlugin): "filename": node.filename.get() } ) + + # Collect focal length. + data = { + "cameraFocalLength": cmds.getAttr(camera + ".focalLength") + } + + try: + instance.data["customData"].update(data) + except KeyError: + instance.data["customData"] = data From d24c4e03dd41faa775efdc57b31b3cc3132f10b8 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 17:56:50 +0800 Subject: [PATCH 02/59] 3dsmax: render instance settings in creator --- .../hosts/max/plugins/create/create_render.py | 50 +++++++++++++++++++ .../max/plugins/publish/collect_render.py | 11 +++- .../deadline/plugins/publish/collect_pools.py | 2 +- .../plugins/publish/submit_max_deadline.py | 13 +++-- 4 files changed, 66 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/max/plugins/create/create_render.py b/openpype/hosts/max/plugins/create/create_render.py index 269fff2e32..31e3ddcb09 100644 --- a/openpype/hosts/max/plugins/create/create_render.py +++ b/openpype/hosts/max/plugins/create/create_render.py @@ -1,8 +1,22 @@ # -*- coding: utf-8 -*- """Creator plugin for creating camera.""" from openpype.hosts.max.api import plugin +from openpype.lib import ( + TextDef, + BoolDef, + NumberDef, +) from openpype.pipeline import CreatedInstance from openpype.hosts.max.api.lib_rendersettings import RenderSettings +from openpype.settings import get_project_settings +from openpype.pipeline import legacy_io + + +def setting(project_setting=None): + render_setting = get_project_settings( + legacy_io.Session["AVALON_PROJECT"] + ) + return render_setting["deadline"]["publish"]["MaxSubmitDeadline"] class CreateRender(plugin.MaxCreator): @@ -31,3 +45,39 @@ class CreateRender(plugin.MaxCreator): RenderSettings().set_render_camera(sel_obj) # set output paths for rendering(mandatory for deadline) RenderSettings().render_output(container_name) + + def get_instance_attr_defs(self): + return [ + BoolDef("use_published", + default=setting()["active"], + label="Use Published Scene"), + + NumberDef("priority", + minimum=1, + maximum=250, + decimals=0, + default=setting()["priority"], + label="Priority"), + + NumberDef("chunkSize", + minimum=1, + maximum=50, + decimals=0, + default=setting()["chunk_size"], + label="Chunk Size"), + + TextDef("group", + default=setting()["group"], + label="Group Name"), + + TextDef("deadline_pool", + default=setting()["deadline_pool"], + label="Deadline Pool"), + + TextDef("deadline_pool_secondary", + default=setting()["deadline_pool_secondary"], + label="Deadline Pool Secondary") + ] + + def get_pre_create_attr_defs(self): + return self.get_instance_attr_defs() diff --git a/openpype/hosts/max/plugins/publish/collect_render.py b/openpype/hosts/max/plugins/publish/collect_render.py index 7c9e311c2f..357135750f 100644 --- a/openpype/hosts/max/plugins/publish/collect_render.py +++ b/openpype/hosts/max/plugins/publish/collect_render.py @@ -47,11 +47,13 @@ class CollectRender(pyblish.api.InstancePlugin): self.log.debug(f"Setting {version_int} to context.") context.data["version"] = version_int + creator_attr = instance.data["creator_attributes"] + # setup the plugin as 3dsmax for the internal renderer data = { "subset": instance.name, "asset": asset, - "publish": True, + "publish": creator_attr["use_published"], "maxversion": str(get_max_version()), "imageFormat": img_format, "family": 'maxrender', @@ -61,7 +63,12 @@ class CollectRender(pyblish.api.InstancePlugin): "plugin": "3dsmax", "frameStart": context.data['frameStart'], "frameEnd": context.data['frameEnd'], - "version": version_int + "version": version_int, + "priority": creator_attr["priority"], + "chunkSize": creator_attr["chunkSize"], + "group": creator_attr["group"], + "primaryPool": creator_attr["deadline_pool"], + "secondaryPool": creator_attr["deadline_pool_secondary"] } self.log.info("data: {0}".format(data)) instance.data.update(data) diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py index 48130848d5..c9b4f485d8 100644 --- a/openpype/modules/deadline/plugins/publish/collect_pools.py +++ b/openpype/modules/deadline/plugins/publish/collect_pools.py @@ -10,7 +10,7 @@ class CollectDeadlinePools(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder + 0.420 label = "Collect Deadline Pools" - families = ["rendering", "render.farm", "renderFarm", "renderlayer"] + families = ["rendering", "render.farm", "renderFarm", "renderlayer", "maxrender"] primary_pool = None secondary_pool = None diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 417a03de74..6d62dd7f33 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -21,7 +21,7 @@ class MaxPluginInfo(object): SaveFile = attr.ib(default=True) IgnoreInputs = attr.ib(default=True) - +#TODO: add the optional attirbute class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): label = "Submit Render to Deadline" @@ -49,11 +49,13 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): instance = self._instance context = instance.context - # Always use the original work file name for the Job name even when # rendering is done from the published Work File. The original work # file name is clearer because it can also have subversion strings, # etc. which are stripped for the published file. + if not instance.data.get("publish"): + self.use_published = False + src_filepath = context.data["currentFile"] src_filename = os.path.basename(src_filepath) @@ -71,13 +73,10 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): job_info.Pool = instance.data.get("primaryPool") job_info.SecondaryPool = instance.data.get("secondaryPool") - job_info.ChunkSize = instance.data.get("chunkSize", 1) + job_info.ChunkSize = instance.data.get("chunkSize", self.chunk_size) job_info.Comment = context.data.get("comment") job_info.Priority = instance.data.get("priority", self.priority) - job_info.FramesPerTask = instance.data.get("framesPerTask", 1) - - if self.group: - job_info.Group = self.group + job_info.Group = instance.data.get("group", self.group) # Add options from RenderGlobals render_globals = instance.data.get("renderGlobals", {}) From fff1e3f0c1b257d03170fd665ccd09636fc611ad Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 18:08:51 +0800 Subject: [PATCH 03/59] cosmetic fix and add optional for 3dsmax deadline submission --- .../deadline/plugins/publish/collect_pools.py | 6 +++++- .../deadline/plugins/publish/submit_max_deadline.py | 12 +++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py index c9b4f485d8..3a424f9e74 100644 --- a/openpype/modules/deadline/plugins/publish/collect_pools.py +++ b/openpype/modules/deadline/plugins/publish/collect_pools.py @@ -10,7 +10,11 @@ class CollectDeadlinePools(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder + 0.420 label = "Collect Deadline Pools" - families = ["rendering", "render.farm", "renderFarm", "renderlayer", "maxrender"] + families = ["rendering", + "render.farm", + "renderFarm", + "renderlayer", + "maxrender"] primary_pool = None secondary_pool = None diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 6d62dd7f33..1f1a59a8e6 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -3,7 +3,10 @@ import getpass import copy import attr -from openpype.pipeline import legacy_io +from openpype.pipeline import ( + legacy_io, + OptionalPyblishPluginMixin +) from openpype.settings import get_project_settings from openpype.hosts.max.api.lib import ( get_current_renderer, @@ -21,8 +24,8 @@ class MaxPluginInfo(object): SaveFile = attr.ib(default=True) IgnoreInputs = attr.ib(default=True) -#TODO: add the optional attirbute -class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): +class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, + OptionalPyblishPluginMixin): label = "Submit Render to Deadline" hosts = ["max"] @@ -39,6 +42,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): deadline_pool = None deadline_pool_secondary = None framePerTask = 1 + optional = True def get_job_info(self): job_info = DeadlineJobInfo(Plugin="3dsmax") @@ -49,6 +53,8 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): instance = self._instance context = instance.context + if not self.is_active(instance.data): + return # Always use the original work file name for the Job name even when # rendering is done from the published Work File. The original work # file name is clearer because it can also have subversion strings, From 7baa5754e05d6f30794cb265245f8d55a68a0c37 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 18:09:39 +0800 Subject: [PATCH 04/59] cosmetic issue fix --- openpype/modules/deadline/plugins/publish/submit_max_deadline.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 1f1a59a8e6..d04c4b9c09 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -24,6 +24,7 @@ class MaxPluginInfo(object): SaveFile = attr.ib(default=True) IgnoreInputs = attr.ib(default=True) + class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, OptionalPyblishPluginMixin): From 507941c20898a9cf524851189a10176263543116 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 18:36:36 +0800 Subject: [PATCH 05/59] use apply_settings --- .../hosts/max/plugins/create/create_render.py | 32 ++++++++++--------- .../plugins/publish/submit_max_deadline.py | 4 +-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/openpype/hosts/max/plugins/create/create_render.py b/openpype/hosts/max/plugins/create/create_render.py index 31e3ddcb09..dc1605bb5e 100644 --- a/openpype/hosts/max/plugins/create/create_render.py +++ b/openpype/hosts/max/plugins/create/create_render.py @@ -8,15 +8,6 @@ from openpype.lib import ( ) from openpype.pipeline import CreatedInstance from openpype.hosts.max.api.lib_rendersettings import RenderSettings -from openpype.settings import get_project_settings -from openpype.pipeline import legacy_io - - -def setting(project_setting=None): - render_setting = get_project_settings( - legacy_io.Session["AVALON_PROJECT"] - ) - return render_setting["deadline"]["publish"]["MaxSubmitDeadline"] class CreateRender(plugin.MaxCreator): @@ -25,6 +16,17 @@ class CreateRender(plugin.MaxCreator): family = "maxrender" icon = "gear" + def apply_settings(self, project_settings, system_settings): + plugin_settings = ( + project_settings["deadline"]["publish"]["MaxSubmitDeadline"] + ) + self.use_published = plugin_settings["use_published"] + self.priority = plugin_settings["priority"] + self.chunkSize = plugin_settings["chunk_size"] + self.group = plugin_settings["group"] + self.deadline_pool = plugin_settings["deadline_pool"] + self.deadline_pool_secondary = plugin_settings["deadline_pool_secondary"] + def create(self, subset_name, instance_data, pre_create_data): from pymxs import runtime as rt sel_obj = list(rt.selection) @@ -49,33 +51,33 @@ class CreateRender(plugin.MaxCreator): def get_instance_attr_defs(self): return [ BoolDef("use_published", - default=setting()["active"], + default=self.use_published, label="Use Published Scene"), NumberDef("priority", minimum=1, maximum=250, decimals=0, - default=setting()["priority"], + default=self.priority, label="Priority"), NumberDef("chunkSize", minimum=1, maximum=50, decimals=0, - default=setting()["chunk_size"], + default=self.chunkSize, label="Chunk Size"), TextDef("group", - default=setting()["group"], + default=self.group, label="Group Name"), TextDef("deadline_pool", - default=setting()["deadline_pool"], + default=self.deadline_pool, label="Deadline Pool"), TextDef("deadline_pool_secondary", - default=setting()["deadline_pool_secondary"], + default=self.deadline_pool_secondary, label="Deadline Pool Secondary") ] diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index d04c4b9c09..92e06ca765 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -60,8 +60,6 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, # rendering is done from the published Work File. The original work # file name is clearer because it can also have subversion strings, # etc. which are stripped for the published file. - if not instance.data.get("publish"): - self.use_published = False src_filepath = context.data["currentFile"] src_filename = os.path.basename(src_filepath) @@ -80,7 +78,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, job_info.Pool = instance.data.get("primaryPool") job_info.SecondaryPool = instance.data.get("secondaryPool") - job_info.ChunkSize = instance.data.get("chunkSize", self.chunk_size) + job_info.ChunkSize = instance.data.get("chunkSize", 1) job_info.Comment = context.data.get("comment") job_info.Priority = instance.data.get("priority", self.priority) job_info.Group = instance.data.get("group", self.group) From e00ef8210c9fb592bf9ee84c5c8e56df785a2845 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 18:37:58 +0800 Subject: [PATCH 06/59] cosmetic issue fix --- openpype/hosts/max/plugins/create/create_render.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/create/create_render.py b/openpype/hosts/max/plugins/create/create_render.py index dc1605bb5e..a24c5ea000 100644 --- a/openpype/hosts/max/plugins/create/create_render.py +++ b/openpype/hosts/max/plugins/create/create_render.py @@ -25,7 +25,7 @@ class CreateRender(plugin.MaxCreator): self.chunkSize = plugin_settings["chunk_size"] self.group = plugin_settings["group"] self.deadline_pool = plugin_settings["deadline_pool"] - self.deadline_pool_secondary = plugin_settings["deadline_pool_secondary"] + self.pool_secondary = plugin_settings["deadline_pool_secondary"] def create(self, subset_name, instance_data, pre_create_data): from pymxs import runtime as rt @@ -77,7 +77,7 @@ class CreateRender(plugin.MaxCreator): label="Deadline Pool"), TextDef("deadline_pool_secondary", - default=self.deadline_pool_secondary, + default=self.pool_secondary, label="Deadline Pool Secondary") ] From 36db7faab4c763ed58d9ac3a124a54c9ecac5e9b Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 23:51:49 +0800 Subject: [PATCH 07/59] only allows user to set up the attributes in publish tab --- .../hosts/max/plugins/create/create_render.py | 52 ----------- .../max/plugins/publish/collect_render.py | 9 +- .../plugins/publish/submit_max_deadline.py | 86 ++++++++++++++++--- 3 files changed, 77 insertions(+), 70 deletions(-) diff --git a/openpype/hosts/max/plugins/create/create_render.py b/openpype/hosts/max/plugins/create/create_render.py index a24c5ea000..269fff2e32 100644 --- a/openpype/hosts/max/plugins/create/create_render.py +++ b/openpype/hosts/max/plugins/create/create_render.py @@ -1,11 +1,6 @@ # -*- coding: utf-8 -*- """Creator plugin for creating camera.""" from openpype.hosts.max.api import plugin -from openpype.lib import ( - TextDef, - BoolDef, - NumberDef, -) from openpype.pipeline import CreatedInstance from openpype.hosts.max.api.lib_rendersettings import RenderSettings @@ -16,17 +11,6 @@ class CreateRender(plugin.MaxCreator): family = "maxrender" icon = "gear" - def apply_settings(self, project_settings, system_settings): - plugin_settings = ( - project_settings["deadline"]["publish"]["MaxSubmitDeadline"] - ) - self.use_published = plugin_settings["use_published"] - self.priority = plugin_settings["priority"] - self.chunkSize = plugin_settings["chunk_size"] - self.group = plugin_settings["group"] - self.deadline_pool = plugin_settings["deadline_pool"] - self.pool_secondary = plugin_settings["deadline_pool_secondary"] - def create(self, subset_name, instance_data, pre_create_data): from pymxs import runtime as rt sel_obj = list(rt.selection) @@ -47,39 +31,3 @@ class CreateRender(plugin.MaxCreator): RenderSettings().set_render_camera(sel_obj) # set output paths for rendering(mandatory for deadline) RenderSettings().render_output(container_name) - - def get_instance_attr_defs(self): - return [ - BoolDef("use_published", - default=self.use_published, - label="Use Published Scene"), - - NumberDef("priority", - minimum=1, - maximum=250, - decimals=0, - default=self.priority, - label="Priority"), - - NumberDef("chunkSize", - minimum=1, - maximum=50, - decimals=0, - default=self.chunkSize, - label="Chunk Size"), - - TextDef("group", - default=self.group, - label="Group Name"), - - TextDef("deadline_pool", - default=self.deadline_pool, - label="Deadline Pool"), - - TextDef("deadline_pool_secondary", - default=self.pool_secondary, - label="Deadline Pool Secondary") - ] - - def get_pre_create_attr_defs(self): - return self.get_instance_attr_defs() diff --git a/openpype/hosts/max/plugins/publish/collect_render.py b/openpype/hosts/max/plugins/publish/collect_render.py index 357135750f..63e4108c84 100644 --- a/openpype/hosts/max/plugins/publish/collect_render.py +++ b/openpype/hosts/max/plugins/publish/collect_render.py @@ -47,13 +47,11 @@ class CollectRender(pyblish.api.InstancePlugin): self.log.debug(f"Setting {version_int} to context.") context.data["version"] = version_int - creator_attr = instance.data["creator_attributes"] - # setup the plugin as 3dsmax for the internal renderer data = { "subset": instance.name, "asset": asset, - "publish": creator_attr["use_published"], + "publish": True, "maxversion": str(get_max_version()), "imageFormat": img_format, "family": 'maxrender', @@ -64,11 +62,6 @@ class CollectRender(pyblish.api.InstancePlugin): "frameStart": context.data['frameStart'], "frameEnd": context.data['frameEnd'], "version": version_int, - "priority": creator_attr["priority"], - "chunkSize": creator_attr["chunkSize"], - "group": creator_attr["group"], - "primaryPool": creator_attr["deadline_pool"], - "secondaryPool": creator_attr["deadline_pool_secondary"] } self.log.info("data: {0}".format(data)) instance.data.update(data) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 92e06ca765..83ecdfd6af 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -3,9 +3,14 @@ import getpass import copy import attr +from openpype.lib import ( + TextDef, + BoolDef, + NumberDef, +) from openpype.pipeline import ( legacy_io, - OptionalPyblishPluginMixin + OpenPypePyblishPluginMixin ) from openpype.settings import get_project_settings from openpype.hosts.max.api.lib import ( @@ -26,7 +31,7 @@ class MaxPluginInfo(object): class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, - OptionalPyblishPluginMixin): + OpenPypePyblishPluginMixin): label = "Submit Render to Deadline" hosts = ["max"] @@ -36,7 +41,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, use_published = True priority = 50 tile_priority = 50 - chunk_size = 1 + chunkSize = 1 jobInfo = {} pluginInfo = {} group = None @@ -45,6 +50,22 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, framePerTask = 1 optional = True + @classmethod + def apply_settings(cls, project_settings, system_settings): + settings = project_settings["deadline"]["publish"]["MaxSubmitDeadline"] # noqa + + # Take some defaults from settings + cls.use_published = settings.get("use_published", + cls.use_published) + cls.priority = settings.get("priority", + cls.priority) + cls.chunkSize = settings.get("chunk_size", cls.chunkSize) + cls.group = settings.get("group", cls.group) + cls.deadline_pool = settings.get("deadline_pool", + cls.deadline_pool) + cls.deadline_pool_secondary = settings.get("deadline_pool_secondary", + cls.deadline_pool_secondary) + def get_job_info(self): job_info = DeadlineJobInfo(Plugin="3dsmax") @@ -54,8 +75,6 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, instance = self._instance context = instance.context - if not self.is_active(instance.data): - return # Always use the original work file name for the Job name even when # rendering is done from the published Work File. The original work # file name is clearer because it can also have subversion strings, @@ -76,12 +95,22 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, ) job_info.Frames = frames - job_info.Pool = instance.data.get("primaryPool") - job_info.SecondaryPool = instance.data.get("secondaryPool") - job_info.ChunkSize = instance.data.get("chunkSize", 1) + attr_values = self.get_attr_values_from_data(instance.data) + + if attr_values.get("deadline_pool"): + job_info.Pool = attr_values.get("deadline_pool") + else: + job_info.Pool = instance.data.get("primaryPool") + if attr_values.get("deadline_pool_secondary"): + job_info.SecondaryPool = attr_values.get("deadline_pool_secondary") + else: + job_info.SecondaryPool = instance.data.get("secondaryPool", + self.deadline_pool_secondary) + + job_info.ChunkSize = attr_values.get("chunkSize", 1) job_info.Comment = context.data.get("comment") - job_info.Priority = instance.data.get("priority", self.priority) - job_info.Group = instance.data.get("group", self.group) + job_info.Priority = attr_values.get("priority", self.priority) + job_info.Group = attr_values.get("group", self.group) # Add options from RenderGlobals render_globals = instance.data.get("renderGlobals", {}) @@ -220,3 +249,40 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, plugin_info.update(plugin_data) return job_info, plugin_info + + @classmethod + def get_attribute_defs(cls): + defs = super(MaxSubmitDeadline, cls).get_attribute_defs() + defs.extend([ + BoolDef("use_published", + default=cls.use_published, + label="Use Published Scene"), + + NumberDef("priority", + minimum=1, + maximum=250, + decimals=0, + default=cls.priority, + label="Priority"), + + NumberDef("chunkSize", + minimum=1, + maximum=50, + decimals=0, + default=cls.chunkSize, + label="Frame Per Task"), + + TextDef("group", + default=cls.group, + label="Group Name"), + + TextDef("deadline_pool", + default=cls.deadline_pool, + label="Deadline Pool"), + + TextDef("deadline_pool_secondary", + default=cls.deadline_pool_secondary, + label="Deadline Pool Secondary") + ]) + + return defs From fb6bc696f8a5f94b54689c2d4e6c390f8058220c Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 23:54:16 +0800 Subject: [PATCH 08/59] cosmetic issue fix --- .../modules/deadline/plugins/publish/submit_max_deadline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 83ecdfd6af..478c2ce2de 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -105,7 +105,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, job_info.SecondaryPool = attr_values.get("deadline_pool_secondary") else: job_info.SecondaryPool = instance.data.get("secondaryPool", - self.deadline_pool_secondary) + self.deadline_pool_secondary) # noqa job_info.ChunkSize = attr_values.get("chunkSize", 1) job_info.Comment = context.data.get("comment") From 2af4c94e2ca6328328b49bed562c2a4106ba9c90 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 15:43:45 +0800 Subject: [PATCH 09/59] move the pool settings into the pool collectors --- .../deadline/plugins/publish/collect_pools.py | 46 +++++++++++++++++-- .../plugins/publish/submit_max_deadline.py | 25 ++-------- .../publish/validate_deadline_pools.py | 6 ++- 3 files changed, 51 insertions(+), 26 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py index 3a424f9e74..eb84308e9d 100644 --- a/openpype/modules/deadline/plugins/publish/collect_pools.py +++ b/openpype/modules/deadline/plugins/publish/collect_pools.py @@ -3,9 +3,12 @@ """ import pyblish.api +from openpype.lib import TextDef +from openpype.pipeline.publish import OpenPypePyblishPluginMixin -class CollectDeadlinePools(pyblish.api.InstancePlugin): +class CollectDeadlinePools(pyblish.api.InstancePlugin, + OpenPypePyblishPluginMixin): """Collect pools from instance if present, from Setting otherwise.""" order = pyblish.api.CollectorOrder + 0.420 @@ -19,9 +22,46 @@ class CollectDeadlinePools(pyblish.api.InstancePlugin): primary_pool = None secondary_pool = None + @classmethod + def apply_settings(cls, project_settings, system_settings): + # deadline.publish.CollectDeadlinePools + settings = project_settings["deadline"]["publish"]["CollectDeadlinePools"] # noqa + cls.primary_pool = settings.get("primary_pool", None) + cls.secondary_pool = settings.get("secondary_pool", None) + for family in cls.families: + if family == "maxrender": + max_setting = project_settings["deadline"]["publish"]["MaxSubmitDeadline"] # noqa + cls.primary_pool = max_setting.get("deadline_pool", None) + cls.secondary_pool = max_setting.get("deadline_pool_secondary", None) + def process(self, instance): + + attr_values = self.get_attr_values_from_data(instance.data) if not instance.data.get("primaryPool"): - instance.data["primaryPool"] = self.primary_pool or "none" + instance.data["primaryPool"] = ( + attr_values.get("primaryPool") or self.primary_pool or "none" + ) if not instance.data.get("secondaryPool"): - instance.data["secondaryPool"] = self.secondary_pool or "none" + instance.data["secondaryPool"] = ( + attr_values.get("secondaryPool") or self.secondary_pool or "none" # noqa + ) + + @classmethod + def get_attribute_defs(cls): + # TODO: Preferably this would be an enum for the user + # but the Deadline server URL can be dynamic and + # can be set per render instance. Since get_attribute_defs + # can't be dynamic unfortunately EnumDef isn't possible (yet?) + # pool_names = self.deadline_module.get_deadline_pools(deadline_url, + # self.log) + # secondary_pool_names = ["-"] + pool_names + + return [ + TextDef("primaryPool", + label="Primary Pool", + default=cls.primary_pool), + TextDef("secondaryPool", + label="Secondary Pool", + default=cls.secondary_pool) + ] diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 478c2ce2de..c55e85cfb0 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -61,10 +61,6 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, cls.priority) cls.chunkSize = settings.get("chunk_size", cls.chunkSize) cls.group = settings.get("group", cls.group) - cls.deadline_pool = settings.get("deadline_pool", - cls.deadline_pool) - cls.deadline_pool_secondary = settings.get("deadline_pool_secondary", - cls.deadline_pool_secondary) def get_job_info(self): job_info = DeadlineJobInfo(Plugin="3dsmax") @@ -95,17 +91,10 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, ) job_info.Frames = frames - attr_values = self.get_attr_values_from_data(instance.data) + job_info.Pool = instance.data.get("primaryPool") + job_info.SecondaryPool = instance.data.get("secondaryPool") - if attr_values.get("deadline_pool"): - job_info.Pool = attr_values.get("deadline_pool") - else: - job_info.Pool = instance.data.get("primaryPool") - if attr_values.get("deadline_pool_secondary"): - job_info.SecondaryPool = attr_values.get("deadline_pool_secondary") - else: - job_info.SecondaryPool = instance.data.get("secondaryPool", - self.deadline_pool_secondary) # noqa + attr_values = self.get_attr_values_from_data(instance.data) job_info.ChunkSize = attr_values.get("chunkSize", 1) job_info.Comment = context.data.get("comment") @@ -275,14 +264,6 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, TextDef("group", default=cls.group, label="Group Name"), - - TextDef("deadline_pool", - default=cls.deadline_pool, - label="Deadline Pool"), - - TextDef("deadline_pool_secondary", - default=cls.deadline_pool_secondary, - label="Deadline Pool Secondary") ]) return defs diff --git a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py index 78eed17c98..3c02c7933f 100644 --- a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py +++ b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py @@ -17,7 +17,11 @@ class ValidateDeadlinePools(OptionalPyblishPluginMixin, label = "Validate Deadline Pools" order = pyblish.api.ValidatorOrder - families = ["rendering", "render.farm", "renderFarm", "renderlayer"] + families = ["rendering", + "render.farm", + "renderFarm", + "renderlayer", + "maxrender"] optional = True def process(self, instance): From c48fddbba33cdb290c6f86c34bc68bb25a943607 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 15:45:01 +0800 Subject: [PATCH 10/59] cosmetic issue fix --- openpype/modules/deadline/plugins/publish/collect_pools.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py index eb84308e9d..b2732d375f 100644 --- a/openpype/modules/deadline/plugins/publish/collect_pools.py +++ b/openpype/modules/deadline/plugins/publish/collect_pools.py @@ -32,7 +32,8 @@ class CollectDeadlinePools(pyblish.api.InstancePlugin, if family == "maxrender": max_setting = project_settings["deadline"]["publish"]["MaxSubmitDeadline"] # noqa cls.primary_pool = max_setting.get("deadline_pool", None) - cls.secondary_pool = max_setting.get("deadline_pool_secondary", None) + cls.secondary_pool = max_setting.get("deadline_pool_secondary", + None) def process(self, instance): From d8441216e4fa4c8b1b0b1ee2e58d1df4eb2b28a3 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 15:55:07 +0800 Subject: [PATCH 11/59] move the pool settings into the pool collectors --- openpype/modules/deadline/plugins/publish/collect_pools.py | 6 ------ .../modules/deadline/plugins/publish/submit_max_deadline.py | 6 ++++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py index b2732d375f..e221eb00ea 100644 --- a/openpype/modules/deadline/plugins/publish/collect_pools.py +++ b/openpype/modules/deadline/plugins/publish/collect_pools.py @@ -28,12 +28,6 @@ class CollectDeadlinePools(pyblish.api.InstancePlugin, settings = project_settings["deadline"]["publish"]["CollectDeadlinePools"] # noqa cls.primary_pool = settings.get("primary_pool", None) cls.secondary_pool = settings.get("secondary_pool", None) - for family in cls.families: - if family == "maxrender": - max_setting = project_settings["deadline"]["publish"]["MaxSubmitDeadline"] # noqa - cls.primary_pool = max_setting.get("deadline_pool", None) - cls.secondary_pool = max_setting.get("deadline_pool_secondary", - None) def process(self, instance): diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index c55e85cfb0..e681346556 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -91,8 +91,10 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, ) job_info.Frames = frames - job_info.Pool = instance.data.get("primaryPool") - job_info.SecondaryPool = instance.data.get("secondaryPool") + job_info.Pool = instance.data.get("primaryPool", + self.deadline_pool) + job_info.SecondaryPool = instance.data.get("secondaryPool", + self.deadline_pool_secondary) attr_values = self.get_attr_values_from_data(instance.data) From 6c1882236419d68934d6130242ffc9cf75c4eeba Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 15:56:15 +0800 Subject: [PATCH 12/59] hound fix --- .../modules/deadline/plugins/publish/submit_max_deadline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index e681346556..e99752b7ab 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -94,7 +94,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, job_info.Pool = instance.data.get("primaryPool", self.deadline_pool) job_info.SecondaryPool = instance.data.get("secondaryPool", - self.deadline_pool_secondary) + self.deadline_pool_secondary) # noqa attr_values = self.get_attr_values_from_data(instance.data) From 6bdca1561bc14fd024f0d264887f4a2202fbcc79 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 16:00:29 +0800 Subject: [PATCH 13/59] clean up the duplicate attributes for pool settings --- .../deadline/plugins/publish/submit_max_deadline.py | 8 ++------ .../settings/defaults/project_settings/deadline.json | 2 -- .../projects_schema/schema_project_deadline.json | 10 ---------- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index e99752b7ab..65d08b9ef4 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -45,8 +45,6 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, jobInfo = {} pluginInfo = {} group = None - deadline_pool = None - deadline_pool_secondary = None framePerTask = 1 optional = True @@ -91,10 +89,8 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, ) job_info.Frames = frames - job_info.Pool = instance.data.get("primaryPool", - self.deadline_pool) - job_info.SecondaryPool = instance.data.get("secondaryPool", - self.deadline_pool_secondary) # noqa + job_info.Pool = instance.data.get("primaryPool") + job_info.SecondaryPool = instance.data.get("secondaryPool") attr_values = self.get_attr_values_from_data(instance.data) diff --git a/openpype/settings/defaults/project_settings/deadline.json b/openpype/settings/defaults/project_settings/deadline.json index 0cbd323299..dec6a405a0 100644 --- a/openpype/settings/defaults/project_settings/deadline.json +++ b/openpype/settings/defaults/project_settings/deadline.json @@ -44,8 +44,6 @@ "priority": 50, "chunk_size": 10, "group": "none", - "deadline_pool": "", - "deadline_pool_secondary": "", "framePerTask": 1 }, "NukeSubmitDeadline": { diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json index 9906939cc7..29551cc9f8 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json @@ -246,16 +246,6 @@ "key": "group", "label": "Group Name" }, - { - "type": "text", - "key": "deadline_pool", - "label": "Deadline pool" - }, - { - "type": "text", - "key": "deadline_pool_secondary", - "label": "Deadline pool (secondary)" - }, { "type": "number", "key": "framePerTask", From 44120036bf8d8c45fd89cae46837cbe8088c63ed Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 16:03:40 +0800 Subject: [PATCH 14/59] clean up setting --- openpype/settings/defaults/project_settings/deadline.json | 3 +-- .../schemas/projects_schema/schema_project_deadline.json | 7 +------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/openpype/settings/defaults/project_settings/deadline.json b/openpype/settings/defaults/project_settings/deadline.json index dec6a405a0..fdd70f1a44 100644 --- a/openpype/settings/defaults/project_settings/deadline.json +++ b/openpype/settings/defaults/project_settings/deadline.json @@ -43,8 +43,7 @@ "use_published": true, "priority": 50, "chunk_size": 10, - "group": "none", - "framePerTask": 1 + "group": "none" }, "NukeSubmitDeadline": { "enabled": true, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json index 29551cc9f8..d8b5e4dc1f 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json @@ -239,17 +239,12 @@ { "type": "number", "key": "chunk_size", - "label": "Chunk Size" + "label": "Frame per Task" }, { "type": "text", "key": "group", "label": "Group Name" - }, - { - "type": "number", - "key": "framePerTask", - "label": "Frame Per Task" } ] }, From 828f59bfb55e10c2c207c98eab7d6f1184d2826e Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 16:37:58 +0800 Subject: [PATCH 15/59] clean up attributes --- .../modules/deadline/plugins/publish/submit_max_deadline.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 65d08b9ef4..dec4bcc500 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -40,13 +40,10 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, use_published = True priority = 50 - tile_priority = 50 - chunkSize = 1 + chunk_size = 1 jobInfo = {} pluginInfo = {} group = None - framePerTask = 1 - optional = True @classmethod def apply_settings(cls, project_settings, system_settings): From 55b984dc66c4948b793033afe27e111047b62ae1 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 17:45:35 +0800 Subject: [PATCH 16/59] scene length setting for 3dsmax --- openpype/hosts/max/api/lib.py | 127 +++++++++++++++++++++++++++++ openpype/hosts/max/api/menu.py | 21 ++++- openpype/hosts/max/api/pipeline.py | 5 ++ 3 files changed, 152 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 4fb750d91b..f1d1f91dd1 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -6,6 +6,14 @@ from pymxs import runtime as rt from typing import Union import contextlib +from openpype.client import ( + get_project, + get_asset_by_name +) +from openpype.pipeline import legacy_io + +from openpype.pipeline.context_tools import get_current_project_asset + JSON_PREFIX = "JSON::" @@ -157,6 +165,125 @@ def get_multipass_setting(project_setting=None): ["multipass"]) +def set_scene_resolution(width, height): + """Set the render resolution + + Args: + width(int): value of the width + height(int): value of the height + + Returns: + None + + """ + rt.renderWidth = width + rt.renderHeight = height + + +def reset_scene_resolution(): + """Apply the scene resolution from the project definition + + scene resolution can be overwritten by an asset if the asset.data contains + any information regarding scene resolution . + + Returns: + None + """ + project_name = legacy_io.active_project() + project_doc = get_project(project_name) + project_data = project_doc["data"] + asset_data = get_current_project_asset()["data"] + + # Set project resolution + width_key = "resolutionWidth" + height_key = "resolutionHeight" + proj_width_key = project_data.get(width_key, 1920) + proj_height_key = project_data.get(height_key, 1080) + + width = asset_data.get(width_key, proj_width_key) + height = asset_data.get(height_key, proj_height_key) + + set_scene_resolution(width, height) + + +def get_frame_range(): + """Get the current assets frame range and handles.""" + # Set frame start/end + project_name = legacy_io.active_project() + asset_name = legacy_io.Session["AVALON_ASSET"] + asset = get_asset_by_name(project_name, asset_name) + + frame_start = asset["data"].get("frameStart") + frame_end = asset["data"].get("frameEnd") + # Backwards compatibility + if frame_start is None or frame_end is None: + frame_start = asset["data"].get("edit_in") + frame_end = asset["data"].get("edit_out") + + if frame_start is None or frame_end is None: + return + + handles = asset["data"].get("handles") or 0 + handle_start = asset["data"].get("handleStart") + if handle_start is None: + handle_start = handles + + handle_end = asset["data"].get("handleEnd") + if handle_end is None: + handle_end = handles + + return { + "frameStart": frame_start, + "frameEnd": frame_end, + "handleStart": handle_start, + "handleEnd": handle_end + } + + +def reset_frame_range(fps=True): + """Set frame range to current asset + + Args: + animationRange: A System Global variable which lets you get and + set an Interval value that defines the start and end frames + of the Active Time Segment. + frameRate: A System Global variable which lets you get + and set an Integer value that defines the current + scene frame rate in frames-per-second. + """ + if fps: + fps_number = float(legacy_io.Session.get("AVALON_FPS", + 25)) + rt.frameRate = fps_number + + frame_range = get_frame_range() + + frame_start = frame_range["frameStart"] - int(frame_range["handleStart"]) + frame_end = frame_range["frameEnd"] + int(frame_range["handleEnd"]) + + frange_cmd = f"animationRange = interval {frame_start} {frame_end}" + + rt.execute(frange_cmd) + + +def set_context_setting(): + """Apply the project settings from the project definition + + Settings can be overwritten by an asset if the asset.data contains + any information regarding those settings. + + Examples of settings: + frame range + resolution + + Returns: + None + """ + reset_scene_resolution() + + reset_frame_range() + + def get_max_version(): """ Args: diff --git a/openpype/hosts/max/api/menu.py b/openpype/hosts/max/api/menu.py index 5c273b49b4..fdac5eba09 100644 --- a/openpype/hosts/max/api/menu.py +++ b/openpype/hosts/max/api/menu.py @@ -4,7 +4,7 @@ from qtpy import QtWidgets, QtCore from pymxs import runtime as rt from openpype.tools.utils import host_tools - +from openpype.hosts.max.api import lib class OpenPypeMenu(object): """Object representing OpenPype menu. @@ -107,6 +107,17 @@ class OpenPypeMenu(object): workfiles_action = QtWidgets.QAction("Work Files...", openpype_menu) workfiles_action.triggered.connect(self.workfiles_callback) openpype_menu.addAction(workfiles_action) + + openpype_menu.addSeparator() + + res_action = QtWidgets.QAction("Set Resolution", openpype_menu) + res_action.triggered.connect(self.resolution_callback) + openpype_menu.addAction(res_action) + + frame_action = QtWidgets.QAction("Set Frame Range", openpype_menu) + frame_action.triggered.connect(self.frame_range_callback) + openpype_menu.addAction(frame_action) + return openpype_menu def load_callback(self): @@ -128,3 +139,11 @@ class OpenPypeMenu(object): def workfiles_callback(self): """Callback to show Workfiles tool.""" host_tools.show_workfiles(parent=self.main_widget) + + def resolution_callback(self): + """Callback to reset scene resolution""" + return lib.reset_scene_resolution() + + def frame_range_callback(self): + """Callback to reset frame range""" + return lib.reset_frame_range() diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index f8a7b8ea5c..dacc402318 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -50,6 +50,11 @@ class MaxHost(HostBase, IWorkfileHost, ILoadHost, INewPublisher): self._has_been_setup = True + def context_setting(): + return lib.set_context_setting() + rt.callbacks.addScript(rt.Name('systemPostNew'), + context_setting) + def has_unsaved_changes(self): # TODO: how to get it from 3dsmax? return True From a24dcd207cceb8959a832a3c576a59bba0200064 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 18:53:12 +0800 Subject: [PATCH 17/59] renaming chunksize variablesd --- .../modules/deadline/plugins/publish/submit_max_deadline.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index dec4bcc500..c728b6b9c7 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -54,7 +54,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, cls.use_published) cls.priority = settings.get("priority", cls.priority) - cls.chunkSize = settings.get("chunk_size", cls.chunkSize) + cls.chuck_size = settings.get("chunk_size", cls.chunk_size) cls.group = settings.get("group", cls.group) def get_job_info(self): @@ -253,7 +253,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, minimum=1, maximum=50, decimals=0, - default=cls.chunkSize, + default=cls.chunk_size, label="Frame Per Task"), TextDef("group", From c42ce4e96c7d14767d1aa0a62b126ffa43ccd942 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 1 Mar 2023 14:41:51 +0100 Subject: [PATCH 18/59] Enhancement: Adding family requirements option to kitsu note --- .../plugins/publish/integrate_kitsu_note.py | 51 +++++++++++++++++++ .../defaults/project_settings/kitsu.json | 1 + .../projects_schema/schema_project_kitsu.json | 26 ++++++++++ 3 files changed, 78 insertions(+) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 6fda32d85f..8e0037fcf7 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -15,6 +15,7 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): set_status_note = False note_status_shortname = "wfa" status_conditions = list() + family_requirements = list() # comment settings custom_comment_template = { @@ -72,6 +73,56 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): if self.set_status_note and allow_status_change: kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname + families = set() + for instance in context: + if instance.data.get('publish'): + families.add(instance.data['family']) + + # Get note status, by default uses the task status for the note + # if it is not specified in the configuration + kitsu_task = context.data["kitsu_task"] + shortname = kitsu_task["task_status"]["short_name"].upper() + note_status = kitsu_task["task_status_id"] + if self.set_status_note and next( + ( + False + for status_except in self.status_exceptions + if shortname == status_except["short_name"].upper() + and status_except["condition"] == "equal" + or + shortname != status_except["short_name"].upper() + and status_except["condition"] == "not_equal" + ), + True, + ) and next( + ( + True + for family in families + if next( + ( + False + for family_req in self.family_requirements + if family_req['equality'] != 'equal' + and family_req['family'] == family + or + family_req['equality'] == 'not_equal' + and family_req['family'] == family + ), + True, + ) + ), + False, + ): + kitsu_status = gazu.task.get_task_status_by_short_name( + self.note_status_shortname + ) + if kitsu_status: + note_status = kitsu_status + self.log.info("Note Kitsu status: {}".format(note_status)) + else: + self.log.info( + "Cannot find {} status. The status will not be " + "changed!".format(self.note_status_shortname) ) if kitsu_status: note_status = kitsu_status diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index 0638450595..32c6c253c7 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -9,6 +9,7 @@ "set_status_note": false, "note_status_shortname": "wfa", "status_conditions": [], + "family_requirements": [], "custom_comment_template": { "enabled": false, "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index ee309f63a7..c32a2cb5af 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -79,6 +79,31 @@ }, "label": "Status shortname" }, + { + "type": "list", + "key": "family_requirements", + "label": "Family requirements", + "object_type": { + "type": "dict", + "key": "requirement_dict", + "children": [ + { + "type": "enum", + "key": "equality", + "label": "Equality", + "enum_items": [ + {"equal": "Equal"}, + {"not_equal": "Not equal"} + ] + }, + { + "type": "text", + "key": "family", + "label": "Family" + } + ] + } + }, { "type": "dict", "collapsible": true, @@ -102,6 +127,7 @@ "label": "Custom comment" } ] + } } ] } From b467909fd65622f524ff1ba35f2cca53cd62afab Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 1 Mar 2023 14:48:37 +0100 Subject: [PATCH 19/59] Using lower cases for families and a small fix --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 8e0037fcf7..bd43fe3b7c 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -102,11 +102,11 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): ( False for family_req in self.family_requirements - if family_req['equality'] != 'equal' - and family_req['family'] == family + if family_req['equality'] == 'equal' + and family_req['family'].lower() != family or family_req['equality'] == 'not_equal' - and family_req['family'] == family + and family_req['family'].lower() == family ), True, ) From d3330f482a7e4d8945d871e13359f03938577240 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 1 Mar 2023 15:11:56 +0100 Subject: [PATCH 20/59] Edited kitsu module readme --- website/docs/module_kitsu.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index 23898fba2e..08b7073c3d 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -43,10 +43,11 @@ Task status can be automatically set during publish thanks to `Integrate Kitsu N `Admin -> Studio Settings -> Project Settings -> Kitsu -> Integrate Kitsu Note`. -There are three settings available: +There are four settings available: - `Set status on note` -> turns on and off this integrator. - `Note shortname` -> Which status shortname should be set automatically (Case sensitive). - `Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). +- `Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Equality` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you only publish the workfile subset. ![Integrate Kitsu Note project settings](assets/integrate_kitsu_note_settings.png) From 7356887df6402f5d4acfb7448a47aec5b5c33877 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 1 Mar 2023 18:45:15 +0100 Subject: [PATCH 21/59] Renaming equality into condition, made a new screenshot so both equal and not equal settings are shown --- .../plugins/publish/integrate_kitsu_note.py | 4 ++-- .../projects_schema/schema_project_kitsu.json | 4 ++-- .../assets/integrate_kitsu_note_settings.png | Bin 30524 -> 44847 bytes website/docs/module_kitsu.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index bd43fe3b7c..2c85a5f70b 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -102,10 +102,10 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): ( False for family_req in self.family_requirements - if family_req['equality'] == 'equal' + if family_req['condition'] == 'equal' and family_req['family'].lower() != family or - family_req['equality'] == 'not_equal' + family_req['condition'] == 'not_equal' and family_req['family'].lower() == family ), True, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index c32a2cb5af..ba77f2b471 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -89,8 +89,8 @@ "children": [ { "type": "enum", - "key": "equality", - "label": "Equality", + "key": "condition", + "label": "Condition", "enum_items": [ {"equal": "Equal"}, {"not_equal": "Not equal"} diff --git a/website/docs/assets/integrate_kitsu_note_settings.png b/website/docs/assets/integrate_kitsu_note_settings.png index 127e79ab8063dae0408f90a82d6bb4b5e233ed47..fd055942d023e2ffc12fc508cd7079eb834045c3 100644 GIT binary patch literal 44847 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 BT7Uom literal 30524 zcmce;WmsEXyDm!K3T?3pTC6Qlio072MS>Q0DDLhOpoSJGPSN6!AjO?PDNtO41S?iZ zkWe5f2@K-E4U%!UGV`=^ael02=VXPa0$lKNKUOhw2fldu9`o>u^6-gr z^F4m8@>oVzOFlj}2oLWu9_ZCeE#Hi-c^_YzDKPqSn0&(6Go+YNboxc^Jw`lovd9Na z{qB}CL(z&fjbeVzkuK%u&40X{w|>NA(lM(pKbUoo;1H{`gzDuoM#ev{OnChALFvZF zjrPByINEoH&?KLg-Wt78h$Pips92Aq+Zy=7xAp+rWwdpVY_V*Kyx(zDv%=lw;MxE;*fjm*x3oJtKeaXC(X_fEFTfZg8CDZ8id%2Xlf zCZ{+obI=-Y>@&|9#%JQPJzciY76j6;(e-JFhTFrNYHLy3n+$)iMtKC=-C;Of8&X~# z*??|;dy7_hWH%;Kw5ZKFnwO8y^X!;~Rw_s_UaQi*(cT_X<6`<=HAB2CV5d#9vXY1O zr)hpH_<*Ojre?EtsvcTcsMyu@F)}(jX=(*tqRAmT;;JA3Pl6P)PYoFdz$ZMV;}67O z`=4q4{J}1fWKU>4cGb4W$4z`ry!^R%HbD=?tqmwuMt@&qt*=`I7JIA4V`@QvmWYs$ zg@M7iv$Ipwtx6x5J2{6zaS~gygR84T7Ui+Vz4&qYV+s(%Y6}tAFpBUZ`puY zxlCC>X?K-bNbkxzuI!({7e-60`pF#}=V<9bL%qGpj3P9|H)URKBU(-0vdAS~t)cF3 z+Oj$@C%5VLFLsbhkE*S&uby9{2rCCiQ>jIO|B&rb);X~12K9A1u>Dz*lE=YIrQ2nb z)Xt-BxVf}9Z_pNXJKWD;LLOIYA})SAQ-$Ur1Oy_ZqB08#*0wG=`0D6H+?CZX&RDh= zTGd8J)gfijIL42kkm_5{PY=EZczV{DTbP&opW_}ElHTLhia7lB>vIg9METxcfq@}R z&d?ORk}F6z{DF~$S;(-~L8o^U(Dq|nZ(A#Aa~;|?%sN5(9-aVxJc8aLJf(u zGiZfqBqgn(HaDjnDq5L9_AY2G&2cwbS@{x(`^UMJhoa!7wfQ#otEUqE&@ic;46n(9 zUW_lnqNuZc>rq#0`exx6+!j7taT@n`X#J-C_l44b7p)%(TI|bs7G-gk;kim!{I8<> z!?}T{fmZ6ni{{gT-CE(R%z&qxxwszHkok|<|9@tL|D1+Osi7`Zp6=wUhDN-NlSQQh zz3)aVwp|9D&}HsN0d2-ADn%VkThMFh>-PqxTzUNz(P?02LsOF?J~6)$T#`O;H>jYX zaA11U_qh0Qr?qC^GQWt0jad^2m+!OB<{r8?c9W*w{ZL<~SE=0E3VuXM8P7-+$}cMF zO;-Nq;-n?0(a2)YuXW$Juk@(|Gje(T>MgqcEul6bU5OV;W5{uiJvCLuc&z^^*GWTP zA6cK#XC8(`T5-=;_$0Jo82M$_PMM56=x)8{%2T&P@nZNH)#YM5y}zi-@~@l>K{ zChN)-jfj%>Ahq4_otk29<};t8FH7N0k{5qs71M}^b=h8IQ~O=4ab?4c`voi(e-Bb8 z#V3}6PpP%kE2UNCTd?@IFxW%dJ!Rh-Gw}SUl0Lv`rB0AsHGcbYYiqwZW^C#e;sqCK zU&b6CyEfN*Z%zJLDLOb_iB*Wt@?B<*&(FwUFDoz6P*kjHq00txTY*fpyd|ZEzkeFa z-XSqLE%&pTt*_-PG2l0U{#=8ztEg3*v^hpRc=*tgGSvU{R*l8Fvr2=6!RNRfe7fmU ziBsa|4jq44Sy}aMVo<+w7$T#hN5`z9$R5(>#SA&Op8O`h`TmJ^sZn`a8teA#)K}nj zo!O@Ib;fJ`DbEF%WLKO4Bj=zC3z8s>-|sx(6=mA)8t?r5v8#`$bx-z~{C7?`P@B}L zZYt~8fOAZJjpNLNf_z3OEci{gK$(8EVifsWFEV^8KUkw|I}_0wkS(3_`p5b~A6vyR z*66{53<$JL-CH&JueTwhV$HQS!$BwK2}=f9{@6yO;LI2Qz1|`%0|QI{L0r%{s|ICr zEg$*?uQxU|v5MaX*J^38>lzzJqfqvV@$sY!JFeZ(wxHUkrT~7Fy9)lCc2a!)+YaPt zU%S=|F`sRC8<+wg`-b~#T%0;c!@;51dj|nb?QIkSFd3QEEY!E;iOZ%adYTD{c9KDz zX9T0&Iabul+InMm)Iv0{0rd98iV&Sg+mSxRhgKWP=~XV_9s;Z_AZ-Rk11b++};9d_jgN?&qC!(&Z&kbe}BO4QZZ*k zW>D3vQxurjEtQPx;p=b!bcoGEQWFQ^zaaI1w;$D)q^XtHv!jA1btKKsVYi{_-X zwA_n}YbVU-g;RvUivF79a~ZFzD2R{WfBCKGbl}td`PS1%xH?-J1z zU`E;3XYlpIjUvG7$^Z{l@fC*{S1a~{B0MHX5R-*Mb?DDsPbILsVXLm)Y^=x>w(6mk56un8>V}EWs;DG|hRPl6_0N*t zzJVDzU8G(*9_gAgGg^S|#9==d>aHg<7IjiBkOvFC9%dR9nP0H3?OO^@FjH2OGHq>A zR7y@n9U#eR?H$M7-LylvcJMm@HGmY^m=QoMVdGyLyqH6^J=|(40d|W+cRButYcHJ` z+**(9BTEx+MtJ-9#EObGDaY~<%9v!Uxm8vozU7$YyioukDOg=B)<*O*hjE==%&{+q zgs`}*)k7{_vnZ`LaOOc$GI_6*KuJk&$b(E`BH~zETiaJYi{PTrFnRu^tlRiCFSz%L z_l+Fuka53(`jl>axsOSB?PUlS^`jI6Az zikX??Xr-_U7E&$qcQRH5e8DdMb+~zXdV2Q@2$pY^DwC0~ISdGt16!YBK~6HD-q)n(JRi zhs6$Qe#9-wy%|R-Z2>ev=u)@O<@r%DS{XK%b%%-h8S52TXLv+UpN*mHhnp4=;f9w} zedk-K?CoXY&^IXD*m!=@B3WBgXNO+6W&AtM5;wwi-W(x_yTG#<6m$vz7W|5`{gV6l z@h=?4LyRFjIGV2D-5V3`JzQGG3%T>15BH7t?0@Eq?{@zl5aCdT@YX#q>I|k35_jWJ zy@Ivv+Ux(PiQ|X$`VzfHBl^<~3y5B$`0~X~Dk|)>JpDL;jhH~ay}kYiaU}NVO`_v% zLM{u%IDW?Q^JfEVt;zNUJ2~l)ZcGO}=! zjZ7b>0u@ACN$FHT#Pl(Df%;TxH}l+7{-sZXnL=Kk#lG&~$3y8b_)tbB*gX=V>%ZedYV z7ZmO8US(BpC?NQI^6m9#dk6Gw`h3W`gu1AyD-h5S147a&ktxd(*fz`_+UghwY0SzGyS(IN5gePG{_O zx4YhJ)}PEV+5YSEEqwf>goFa3&A~;xv$7B9`W#VhF9s`=SGxJN^2zwf$~O8B zWsHXR7tGB$mX$}G$-ZL*5+;;e%CtyTkPSgsfNg^7p2c{``KL{mLA8NumS%`Z{PHDd zYfE{2MKO|~##OyM&2W~CFti3>=>QjD0&PxBvGDQ9gvHX017+&&jlUlGs2Qn)ueMnt zJ;iQzU3#za{sxpbgN-%0-?^SmDmaI*^R?3KTI+t`f8d5fdHRd5SGeKJBBZ2*1*D;& z@h;8Kz-x7bhl=9H5dix=x28b=vDv^mtD<6G2Dojn&tcEEb(zh69$3 z^;HV?ct!z1LF5aWye;o^I`FZ~5*Ov~@+B{T*`&Fu6_=OGmGpw*3m4f^@>la;(b|hc z-iHyJdK+IE&5&B}leI{fTyYrg0RqMSrFo5rkQkD)^bM#%Ps<-W)ymQN`lu<#X5D)K zQpHz7F-8?v_K|)hw4%8U)51UnL++^f{9Jo9-e1x3EM@ad+6eHIc*crFE>P8swdo9k zo6xUiT(fC@2PxaTY`&tr`5C|<*04Wr<2{Yt-An-Ref^Lw7T_7bw|ck7EVguF%}L3WPH5 zjYf*9syg8LM*sjdsA}LhpMCc(kcu}kBeC>(v$3(U#NAu(3)l64J@yVrl#@4FYNxuL zN-vbsEHq!zw$Qd4(Cy?zdw(|iQ&VDQW{Eab2hy5n*q@R-IK4PJS^$7OyS2!*DtTEJ zCJ_)%B~SIO6(z{_j+lVBcce_Velmx;^jbAbz(o1MSMsb_uc0OVn1B@2Yn zl%bfnEMY8HYmGK20)!(CKwLQmJ4`WQ(0{Or+1W)+P1*)E&(%0Mwh=zRevwUW?w?GI zgXIdWn9>f^kU(?`2n&-|Zg+&rd3k%`3U*(AN-=V}mnshp2A|`YTH#;Ul9EVq?@UP0 z)HOIv>^zf2^+No15p>y05wGmkIhwn9w>q zj=g;!_Pd!M7cdPwJWkZOi;!yT^g6H-2j$<2Y0|%B*MF7K|7D&1ZwGwGNlU5dr?|J^ zHDvMpzb)MV?F0Y!P1@QwZvPmm6j>8woVmPg4xgONp)d{XI!JAprUWQIq_%9uxR|?Y zd0E=a+uOn2-F?CS%334psrjEC`$%#?XVjIE=}aNbC_uIwzt(eA*-VS-G9Lx_Vq|1Y zTK%J|;Zs9iLVGm5-O=^^Ywj#!Vw(E;U(zx%#@fI{K=~;j8#6D{*93T0VM_~*fKa`C zPt1H|Z0rGJEMpF{3nR$!GDO24K`R@ZUOKV@K$mm^uL(rQHe&!ix_>Er3ZLFT zTRJocD0(^%ckU!5kwKf9G*pXZcK+PiMpUagm2EFMH0{zbs|gOTJ6-Mnz;fvA;dm{e zjt@(o<^ukel#&9)r)$u4a@rR4g6JcWC4gK!UgzZUVb*1#Mg9HzPXDD-DIMu|n)GMw zE_RllTC}vr2GvalEG!@_QZ1+)5EeFtCfEc7th!H7s7c$)i}(KL(e;2d@KO3nrYOAB zX?8*DIq8Ii&mxcoSZkeTy(LZu2(YU~lDVehm`{NA6`w!X;#g(~(;1dHeRm5#EHNQH z?`Y1aJ}U@IMMO+2FMgGpeqlZ5Rc5nP0M!Dpn+arWJim8(rl_bGIW5S-qYi8dqSYpw zuyX{UVnB`3*3x}4F^Tch^KP52<`QuLlpui=XQKEKGI);YLeSM1S|FXiP^OLw*g9M)>zRXMg zvgB~5mCQf!`2fRy?VCPmtu1ep!q^M!&GF2AbI_izIPa$~46rh8G5kFFlOH*a3Nee>G8*_eq*b_v|^Mgho)eF|y`{H@r-$`xkq zx&~z`DkK17`}zmfFLGr?{gw}E8?TUMh(mYX7}I` zYU}BJ1+aye&(VijZJqMhN=oV7J@bGbs%^vz&KO5(1q2i!X2o!d0giy7P>N)vtH^;b zl8y7unIhxRtu6NXI_D%xt4+}{OmJ8HEYdnz;$jCUydaDVN zu9_$O0wM+2+FA(2C}(og8)#9)s==U!~^;NqwM` zwXoMOKD+G=UVaEGLQDNI-SY$Q8xvnGsi=o0khzTjZC+7PHNML{4(RHj;81?v<)^|| z3Hxc28NgN3Xoh^t$|{mNmtJ#|j_v;XYT|FV8JKd#dm2>#N!NG}>sM=>uH1kV|KBgk z%*UIqU`aX zKR1{#_2yl?n8QQB(>EYfxc=X--`zi}^BKZoO8`(8KQTL1aZVJ*i4+FZO+XCP)=LcL z=ufXV02*<)*C$U33eZWi)(1!rOI^kj(~3WE*3@s5CR^*TK#15R03*)MKI#Sr8W==Q zmX_A$$1nf9e5N?uL5-N!zPdpl_&G<-f{|DwSnq7!YmX zB1Ss^MA7-asRrcd8moRN;#-?4pnikmB@ah?091RBkbNNyWDkg*e))%2MTO6p;lPqk znFJ_(`9g&gZ2|H(GFj%L5bq2Fw*tflr z)-L|$8n?W%%+JdU0iTjUnomEGTUy$#7*jKXFkVn?(|S?yrl5i&T>WS-TMNBAy#DE-EZ54;LUV~^k8 z$L!=xvP*0kcoQe!8bId`*DpLjzYg$nBXy2y5C}B7T=n!MP_h+ZPIqs-yAQNiiAzdL zU%f2}Ioxr1{f6~x>IUU}U5-hDW&)ylJp}01M#eiG}Sc>u<@PUABK@$i1Cb;to0{97Z8vITuE0; ziJLUiw^b=6vCq8Hc1)_Eq$En-Z&<`_xn{DgOq-jMFnip&p2dUBd=&Xr}IY~ z`bH332Wq7K8$fb_@V<;ed+j3G=bt5(J74jj&=I8Jv}|3 zG-B)6%Y{z9Bavk?dZE@uue#wEkBjfb%11=p;X{N<=TLQsFfr*1Kv{uacy8*3?abDA z?2vutd97Eq0Z`rIh&5eYV9%aC)6&q$Ml)|D#`(di;ro%q9+{J`0PM)c$sVix0R1ulc2U_qN9!k)r z=HUUvg8NIn9n{V!SGK)&t?iaF91!42RK^* zAQIeLh>K+G>`DrcPR>s9GsS#1FHVI3n9S570qA*vLdVL+HVQs+8XNib6~M4S^HMcS z9DI18jK5aUPu_o@Uh14(w7KH=0+>EtL+!4ncDzm^7eU3N%%sK_PzWn0vH_5uX(ip2 zJ6^nwqDc9<1V?Z|Gin!(yTVIO( z;>8yRw5~?fmzWsN+PXTn4y4u~q%YjbdmB;YR&UrPd(+_CV-=wL2hb1$ef9Dt#3L0| zEC#XZ(zk*E02FFa$Oky|0I9P7_~2nCq8`0xeeVE60(31Vqw3Jpjk;m6G@7~NIaOm1 z8jV&Edt=Z?qGHnErbg||OdMO%w9}8xX=@8QISb-2N@b3c1$vMC zQk1xL`1C9_Js#2Rtq-hMvP^heAN2V0A$mLlY~ zPD89~%)eO|=$MBSbve$r{hj*>M5{1g3EyW6;_9NSAN!iN1L#3R`Ap_$-@Fl{yvg^B z?b0e+ut}NVYFV6ia@1j%uiOFDKTZ~Wr$eN_@&)zYq>)Cp56A4+ zy=K-$J3HLkIzJII_BBb_h7Y4RN8g6c)||`GVlN6!)uc2#BYe|IVS$@UhXhn9m z;_LI_eawZ82PPrm4r>3^7rFqoHhG^_Kd#e^j}e;KbZrvv=7tD zTuP9#9et<*!j49~YAt#r9o*plN?oUfvmcrwwv0K#*RVNg<+swvHkHViy>m^Uaa;Id z(WRr}#FWdXZaH5u2Z?vdu*GrN-(GR=}w8=a|6?vltOadM9F4*J?i~uHP6P2q)I8_ zQZx#1CE7m_g`>^O2|_k0Get06^M!RV#2eE+bfUa&pnbZ%yq!W`)w!L=Ss?*zScu`Q z3R#v|PoAgcbGhJV=NG|?pCRN^1NYa1Tgps(9lca_(KgM*#n-|9St4^~zpA}gs367P*5N1ubeOw%M`{tD<5FO!Dt&%+Qjt;*QK z1*J$X;rUh@-F!NFvbt<2e0%+YRni5-`85eFHSZzAC~g7GNMs#PkEm~X`tvKM2PYLh zPtW11pq)rT-8v|mrBH}>r@2<9fY}5OE60vq^lzVIkKI$+nz#hagX#4JA!@B@1>GH# zaI2Gp!DujIlD6VWg-SLny}DDfT5L-qN6KO$36~qvkoxps!NwiqbE>KRWob%Hjd7z< zr-+e-Nw7E=R;?CX%dEmxC*~PYu4@V_Gd+?>fSN6KEuCkKSZ>7sRm1!%iLcKL!8sR% z+OxSj4cXu|uQgsL6M9ft_C-{bCJ#Lahtkh`$YEy2pV;N_eeLsvU0_~Uy$h8!-g(|S zMpdLjz{T;ZHd-FJBTJW5bh1Wb;A!u9Sn_L!1?qj&#cHX?FKGwwc&oQ2dR^C3<)sYD zTOR4t*PTR5KN3D%$a&PYKIC=-aQbm6dgVAN%ea6(NU*)aXyHdXk-VYHM>9gPjJ*^! zKPhT9;N`w#Oe#bEJ5I*L0>s@4@qj1T54gZ{tEc|FSo+WgX4IE4N&o8!^0X)3GAXC2 z^rzG{FPn1tdFN&m$86$;3ZI^mMF#?@?3v?GuI-bWST9qJW{V66mi?V9^_4$d!p+=o#(?CJ?ypP-| zzB#5AT!PvkpeY-SB>5>}l@x$FJ9=XCY^%zkkV1waYyR-?2v#H=4~`M2!;14=`YC^8 zZ1!p@XP1B7>H_WH&NqoQwyTVTG3wo;*K!+6Gzlo?YvJg2e*VOMC!301LiFn~`~Lkk zT8YzI{<4F3aw3A>k$poGZl^0%Y<U;uPU8PWMxK@;mKYtL`mmuZo z*3SET$n`E2`T2q6yDae}ZV6OViP~mx+eYq6u2X1RYo%^*y_Bq4J>yUAe3-Em_qyL- zPohdiVV(EMG)lM6Y*K>#Nlz9@m^Q1Sp%|gfTL;Je`g~Z*gPFBYcYCR{!6Gps z(xDUUwJZ{xzK5cO$OpOw#Di{{w_0_qdhk8X84cnsD;4x(LWVL3=DI&_JBjkr`bkT= zp9TSdCLfk-nee1p`_Ui6r27F?*~N$^(u;4D4%u;d10sQM+TB zi6jXQa{S}l08Z4#B|v+gRT6zqcYc4lZ<0k8bLF8Odf-BPJsv@snBvbD4enYnI}dwa zUpuoCck%h<31%P##}f59CrMUKFqyXJo}X7PZ5pNVN-)jY$C+$L>Vn4d>Db--os%5N zWt23YkqPym&aP92=In5Aq-{LPuFhm^ovAgf@Y&Yb_`VvXqY!H1><{RGSQ4vLu;JCw z02dF zvBtx7qBU+g@)f~fWw>fY4%S-vD2SUY-bmwe%S(_&5cC2)MA%rwE-LsSkHd-h9Mw9H zO8>U`9@aZ5C6K=%=7X_schK!=Fjf=DrWc5wxQMWbz;0rnNbJ8zF-j2JMn-E^JNUnv zvgbMY0=ZAdtZL6|sh%=h&b1xWQaod`@N?v{jB2bdOmvON;J{xu<09wDp7|T}L@@ue zerGB;*TOghR9jS(G*4ooZl=pqkl%0-D)nbfejDLN;3k zX8Al!j|==9fjef}fkmfy*n{v*iv4bPF?AMsrSpG&r zg8&i=x4?ax&_5WFf`v7huz~ht!G;j(X5_`=y zQ!2Nd6V5A5LglNSu;S^d1*SRyWKW+hM)xqwZJtdrb>!g@A?mVaXG99EG7=JY=ONCj zg~q*uuX_)q{rB3O!B%Q%Sq>gUh~(W*n`veWYIA(WQo-XnDYLo1n`v;Ph2j|A3(`{6 zl=N>;z!v#J^kVc|5_M9xQ3D#crBlUAyXf7rRY-jJLQlZeg*1>sRu}y`oPBY_B!)zYaTcL)h z2#vKiQ#SG8Jah#R!faN)Gk3K?akc*n)v0{UUu5-ma7xx)2+{W8N*mD{$#tOxjKN*N6sa!qsAkk%m5p zNQYBROuAr^JMFdeo=mX28scC);SLtn#t#m{d|ue!Y}w_3!OUMJQ3bW48;yX82E+19 zgTJ|JT~2)F%|mMw1U3N~2p!BR4?vE+hkrf#lPz`m{-ZNE(4jCb)S^aoya)g>MNad7 z9_=9xO7`xO!f1L@yGrc)1R+x)bFAH_Ta!1E^>_0S-1)7YIspUs&`q{JWtR6w{#1#6RR{z<8t5G5~@DyJD;tk|4l zFm&fUZ4{uf9m%9dPs9!dc?;755{WkVJuQIZ%gGfkQdATdYjt*9Us?&;{qfKri!AEQ zCR#a5JXcBI(ec=~n-5sDzB>365;eCxUPpAk?Du7Sp`e|(5NjI$*2bGrK>A5E_muN{i23S3&b+7!G9!biw*y*j!wq`Fpa!-+Q_#~j~x*>Yz;;? zFKU{b#{(@u&gN&hG$B-P=)ZcB0h>-LG+kKCDaMKOFGimZ~6f22?!|cYM=Uf(@aUQNMdepbq^*W&$=f2u1Xjf z)aQN!zA0jwVy4iV^~I|;dRRP25S;bp^2S0?78x?ZKM+}5wQ`-8ot(q-#=)wubi;Ot z%kS1ZkI0E&PKLjnz#QQO8$&Ii`Rw3}s2eWrko=9$Sc#M)u^|bG`A0O5M*7Ie5Va0P zlM|Enmu+C6a|nS}j7M>`ef^#*Eh{UFoUXJeJO{d(w(esU7CkY@Bwdry-vMYi(j{=E z%Kq;-We`^qU8&rpr`9+~@p_M4L+&rRj@W3|d04+5a=YbaZH}#zeKbmYFmrH1ONE%H zKA}a`J9x`(UIwtqAS+*jJT1>5GaHL-75QRQ0+CV1Xpb9;x-^Aw>o;-LkJhfGg>|uUz5G}*FD61QNW;y|4N_V>vDDpp_r{PEY|-!7to1S{?0Yus zpo=Rr69UdQ@m;zJ8tdnR6%m=K_;#`G~M#PlA9Do4?TyU#?o<8Pj$RS z+6`2AcWv?|G5CKSDO;bV>2ter5TIm)HPOt?NBR`7*er+9xCCpy&72XVLM&PWaAG6p-7&zJ!N>3nS#hr2mn^?J&Y0IhaZFB%M**Gv=fIrz5>Ku z&k^>vZhQHU!pzHyVej!tP^0qn@G7f*enH8?ogHV8MnFI_aQ?2=d`)qCw%Mhd2X+Ck z`2IvczPq~{I4PftKp1H2XrY$m>A$ocPV3FP_0aMmaGT#ydp~ROH~?y@#L`HhGqrh-x(E=S#3A| zY#Y(2d3iE_N$3JCD}zg<3q8F0d%zF4{;Wy&s^PDBuj5fcGBDeo78-UL7W`UOHKy$l zUID4BRFBts{rW4{B}Nxe&@q* zTf;|2xO?KpArOdV?X>5y=2&tqOhI=}D7(9l2PFBSUW6?Hk{r7R7xFHbVu)BeS^KboE zxKF->-9J~aRvljNu|K`~jQzy~44O4ww$^ihK4%t=`~0MG_Er2m@YE;aC`r8EZhPgs z0`IcH(S^g`&#gm|+5Ay|IbJcQy~kcut1B6`Qa|2GsB|Y(jPz=R$a{_qjlupIH~(b=Ea ze!nx3Y?8Mlskt&K5d1~fS&}vU*Bbc)oBuTaDaS1N)hqAYy^Xi|`znt7x!=G4rf?^1 zNO+BjyM{QO8e^f|KT}11KfAz#3jlwQbA0>8yCp#Tf9|)F%UbS#&b8C?>5B zJA84G;7U6kbAMOB-&E8j_Q3LPl;WQg`|q@oxK+Fz6pROxdcl1!KfpkUY1rnj7;o~P zi{z^RjT#^kEx4{5xA#iM7QIrTEZD8ZWvejrpeW&qU-hv59GYz z$OZ4K{odfjp$LBP@O|ImFG>TUHm+#HSeFB3dwkOmv`ZbuB~PvA#~bz}ooib1azpl@ z!75{m6&2`e{|SK`ah-=N_Nn_uOwm~+6y$l#5|8dtz4}0X8I0i%5TrC zo5{agVV_ewGbDNIq%O8A9++oi*7eLxhxC5!+Rdkui-a!*e-Yfy5_oV1pE%4Wy!C3! zP<{Z#+)>x|Y25%4W*WL3`OF+`;MfmA*IDo0oFHsVJr2G|jD!Y9tby{k5Iya6Am7cG zXExDat#`W^TQHAb3+?Y@2J&?{Q&DypJoVvXz^(|j*WKyzE;>V*K5X443bbguxnn!P zF!Lj5S4udrpe&eNV|XPZzowM+pP=K1)IEElp&<@9(AmIVr!YZPNy{;vI5oLh@^AQJ zl>QOPJ3EXM>&W`D!JH@|+Dm#xqF z@XlPBFEf{|$B}i{6Z=r3S6_#HjYJGx$#dKcx&B6rY^iTi<@uBA(+W;75HR@KP`nY|(<+@M z>HrC+B{Uy#b=B94sO#0s-0ET%purI(RDw-NaV)vT4TsI;!I^Lv`a^<0`O_llwM4_5 zZuyCo^{}g?8TSpDmHe_}sU?|!j+q~&82E5~2`!P;Kn9bz8JD@xB)3OM`Sww6eT(wM zWY_Uuy8}HgAu-zNKUC!>cpoL@>;6A4l{GHj5n0bGfSiN3{^U26IvP){?D{E z$<1~6xBhh&;Md89z*FxE;hab^ve>+;Uq3c0dmAF9TwDiBSs7PBlGqu;v2PmB!?%l1 z4|@(hJJmnWe``DXp}#iy&0Iq@HBOL?;9Kr;tixrhZ%jl%?XdK!*6oAzzY{@z^uRXy zjdO4q>Qs`@=egOaRs4DdWu5G+Nk#ipwP&9%hyaT_zHQ&K0&lO%GJvz4VZCCyV(nwXu-5KyNi#dGBXQ{j)du%~(^Um&-zZauUbkov()0N-u zh95_@pi!E-dTUC$a-OF@b|P5Pn`HkEth%0*?OBQ0&p0=g#Jco`3oFAmjne5A3s9Fh zXHFeQRAHO5?O^r2zl&9-umR`T$;Ss{cMfRYl9AyTCcKEvxiNNYMYIJUFRw7;jXSLA zd+2pB)@wF?LGva?onO62ZW1BH+FJ6e?uEQSJ;p07c0N9(o!6vNM!lz{A_xJ@j7d{; zwE1zzO>WCD%w^88G}Y3vlQDIoXa}2hR6^x>tt0W`4do60nD#{nn)~`}hL}_Nz_z!D zm*aPsGH!;xg`sb}i)c;v)q6=8EYPvqW_l4sr1{2Y=$SOnd zCq7VfyY2s&jAz6bn_04tK4U5$md85ydHP9~X1?9lT@b{}t>?&b$7TZAEF`ryn0YV3 zr?~0ZMA79~il#Q{l{IHqF=n#fC-5Y^RQpHi1)Da-#l16l>ILgl$x}SGN)o)B)iy1o zLrw1ad!!6TM_!-eZ5qUcj@+U3Q-;tmOUubY3+ zoIk`cI*`Ko&`w>|)pDy>JAN?j%9=y{D=-kAq58=zk68ews{86Y#B|Z~FgS~Thg;Qv z+vzr0%7WT*_2R9sj)(NSrG9s(a*U&sU64Tm&#?=Jh!01z57CE2%s&8ANWq5QDiWT8WP zull!(FbVkXi|1|l+UwxhH}1hSZM;Bnau^Bjohu60KVjY~_H9|8yIn|dsm~BG4I>`L z%3_Y@O}FsIKe}vTCWtda$*A5}zoF-G$oj!vW@w`2*D){LzxStzH>{Fe(sE!j5HJ3~w1I4P zDR=LCb8%V_z8hPRu4%W>GVAij7ol>PfEa`TgaRIZMEDz*lG`@fcC_vhIk-NysS@Yi@m>h-K!!o z3heWwoI(G1_z`H0OsXfd`c7EI)@pXFm6^a^Q+-Vh|4zdS@hw8(^sy=pa*2IHsfK;k z-^1zn?a&HXw+xB+&xKYmQ)xm5usw|wI)2GqNcrzI&ZMOxd3|Y6yP{voa$_uXd1ja9!(Wuw z=(D1Sm(W7j`nOBCD3TgU!|Ev=)5EuFKQv|DoM_z?OPot79^`uYJS49vqgZXh&ZDLF z`Y${lYCA{ z?{D$*@B{u*r_uRvE5Ux{=Mux&QUr5@-9=zf?6gV}0;l+xVw9EglDlQhN8Ny796 ztNQr_-1e+^xBcQDwYvDl^PEY33aPkA)7O7}w6M>$*iZDvKPsk#^oO7_-qwaQWsuAH z19THMni*AQ*2TC|ELzy+WT8W5A=^Xm1cMwmC|+|6n<>0#^VlD3IUf?kToTcWCQeLf zVKL~Qey-M6+?4sHrJsBjf==@hgZ=$0?QgH+Z7ssG0ePsYsIZPj4p`hc&F$k?`Vk&7 z26Y@`Hv#0sqqJX4%TK$Gm1Uk2g7klzAJubK1OG)6sdRJJ{xi2wEyXbuTgUbn!)t;G z4l);m{eVa!Qx+Y^yQJ%ZejSfJjijACmU%bp{D0G5+J0N7dh_%16W>;oz_vWo=cHt0 zw5GLYbD^WZ_G|3M8;+NwA|hkD>ztM!F1yj_$^jm}>bZ9+b@nA7*f;FKx}5EA{rsq1 z$G|L!bzoX5KoMTVvKN8$P5*Dw*U;J<~T}VAk`|&8l@0Df6+t=T^>INe_ zg_VeZQTtr4>x`hiuY}oUOJjG@(tV(eir#j8=e8^*b3b6A$bY~~PksIyttv#`J^kWW<>&Xl^T!T(Ge3Jac`5F@`zFYBJyU#tfNw5f zSYplx-KwRnor!J7#b?_yrlDwDh{`s22tK^5kO!)t>de+<;qh;Z=P>stIr$5CKR5yi z#dt&G)3b6shqB!!67N_4t|)VutBWxHBleEv`t$Rl>cqh_BK0py>FjiIm?wHK728_F zAtm*hu2TN}=0+!CEa~Srn1m!`zOK72FPvIIADq;=3eyl>@DaZ63?oTMPw$Tw8tUR# z0shfS<5^^=>Fq$bU4l>&`fDNMNXza|RG6a&51N+B_Ttmi3EHPCS2iZgW?3Rkahyq2 z!eV*@x`x5`J*)oX$x?kx zkrN4x@MrX*8@}rJ4_)IyND?$v%!gBGjvK#dyq6^SfFYEaN>SbI{+BOe$k}=>r3Jn3 zLz!ZYyWgW4R>zbYE_;MUEseS{GV+eQMq=ocU=_xi{KjkiI%XK*sN z1{|54{fPL{EjX8AsIT9VOho;2aPSGG?J2uWz~Ly_#S_%?Xr^Iii;a;S@!enVF}>A5 zg;TI09a)X=LSon%h%``)~H^JdMOwI+*2xk>KLJ^Pfs|G&Kt zUe_n=vzgbaIh)hf(LLrYnwZem`e)_hxfFbShl_X;ztw#y!TZ|3m$`}# zHJ4xh`JA+{o0&w2z@sBGJXQJ@k!*szSTNVvPQtHnUAKn&23g&=-g*6E@P$sPt!IJ7 zX9<(K5)$NG_=1aAlF-6=xZQYr%}{~v@e|^U=ll!x>O+fCgzww*UJ=#r;Tu>CmcDcB zwt*=+jW*}*WLfS^4|G|4IOyQ;sdKdn3lV&CjFaFLncZ_)$7MwF+|sI# zmSVF#sZv2b^upg@8I%{a8pf~ARk}KBs|N5Mw*i3-nN)McRYasqcf?X2A#fEKr>osA8g;G~` zpL~Z$4ZqH(u!5|gtmLgp-I}c5_&1X1fSO9}72jxXz+V92l6|SImn;*zQc`nQA7Zo> z6FJ@hr5EY0jZRHXJ%5xT;l*7%r_-xV=&9}&7Gd7EEP5Mmz0oqXKBSPiPF5x%7=x)l z`nHj1U!jYVvw1KS^qqLWS|5Y;noBVy!u=~Z>qG8a#k#S9_%|dmbIs3|3T7y zNBflx4K`fJZ$`$=&c;(g!RImY7AYxDJgOQhfs~7|R%a?2(q=l9q0)Lbqggu+cgm@| z=mIk}^p?w{Pr~2&Ul6JqMr)(_$;jG5)^3tt2sD16oAdS5s-`Wit!bMEl_i{5u8JL%h@dt6_2RxEv3Omp>hkSp2DO=i|srs1qITO5QQtnLL$@|_kG1DtJmC= zwiiuo23>xqq3kR>ca|cCt*p3<%~1nvJ#{!Qu)d#JoG4);s`SH?6M^kZw97mkYj+*% zc9)+JMpBmGeX0kDfi-b3?_XejG?^ddCWy z@H?dIlA6$;+Oy}Cnj=-n+(il2$q_1d;43~>4H^H#*Zuogb7;$}{ti34aLvZSERWuS z$BNu&TQ`xOW-wbxJvn^hwYMwuhDgoa2rJmaU9=IVc}1|9qMb~;mTt1p}`E!-_4ChU!B$Qq~rteMCWKzkT7<@po}`TYgx$ z|De-CD$=qiM#iF|&eCHcl97zzesIK!aO!9}R3!Nhs)sx0mZ;fP9q*gzn2GUH4;#xA zy_;b+edVd8PR`D>;@7Hozd_M~8Wj;T8bKV~`0-%~PyKt5Q4?T*bc*@~`A z^qV@Cdq;%_A>341a+tfya`SWNRv-DdclAKwuM~sMD<$8LQ+2m+n%kTf{?mU``A>h5 z9`{%CIKu*Hp1RPQ8-pJ8Y_|d9`t#HInlUqcUzPW7gr}gS&X#r zk<(p-t73i1eXmvRU32qtZ%d@kbR=yUlOoW4Wl{B9G3j)4JM{dYdZ6I@8}P>}CXNm+ zo#lJ>Q29qRLgKIT1O3$s7f2p;~gM$IsJ_1w{-~?9G9EX~B z(MemIrCeJKH=rY968d^9dj z=*W=})H%Q*^iHn*Q6G|1_f99F%gn2qYxBtA{sbcIvtAJ`u6L>AiV~J7wWfQ=!gc!n zO6tp4O-WOQE|squ)mDu4`^+v(>EdmxkOWC#>DRj$g!0aCpkPH$+Mv3QTI+5UWtNG&(puu{J!2J$|!&tDag-K90LXf zbN$ZxL{P_qGV51wYyYEwb8@5Az7hqH<4-+;jg0+4jC6_zB1|l9YwA@Hy^yuttE&RE zazlA~A77zh_Zwr+0O#(Xd19`+!msBUD2A2aNa|hOGF4ErtvasF%1SJh$|yA-jHk9t zNpZT@22As{3pD*Isy4ybd(UlLy0BfFU%#q+#N_=k?T{b(h`!+oU+mAAvJMfd-*?XNB?Mg&o^Mr26}l0UIm2JdbWG7Z!$3rw=fA0<^YE@TV|jk!;vdynoJpGkq$>lr zYB@JQ|NGdvZ^-cIPiEANTW!?_=4iP@-|fKsl}|rg9jnx^6>6t zjUDy&LQfmq*7~G^LE0y=5`Q2JnA1i~q#PKnb4u|U2~YeC$n`{uA?CiR`GkckTBV&E z5?+2gr88`!vD}!_!U{ub4%BXWv;^YEG#66Dk6c3?A=gyke&)I7Qhg$u=bZ)zE;#Zj zHo#p?=!6`IC&dkZ*r#}f?q$RjcYEu_VH59<-&kfr0H4D?n}5sqN-2;_T<;Kq_`JHA z1z_^&%{cHySq~-cJyvp%Qxjf6f*< zGblR^?c!9Psz|dlQ#g|gvJo^~4Ht-He*~>eanQm8)K*$NJt#g`1$MpuQpxxBIgqU> zfr15KfMKOQ3hn@F2>F=+Jvd7B2OuK2-e%>nbK+fQe&WN{+!)`FwkUYSnUf1w*Fw%4 zttOV5nVXl|?D6(Wxf2tS2l*Q#gG$$Cp*(OcJ-x0#;PgvAAimxASh@h9qNpf}&$_~G{J54{p&u>G8nwm^pwt#)Z%B36<9I{x0+1^z-Kq>dTa z`!xr@1BpA7&sLvyD2FZEqj*K&5{Fr)y?qdQHAiOFz$mlX)+?#b>(xHrUAd$)qDZMY zzS)i;7EvX9ya{2dkdyB%yCBk}gY}B-EDwe0d)ZeKrh2+39p&;ImZQ`_!ps95?BSsZ z(7S6x#!ND6$WV+C*xg?nj^r(0-$9LmTtF@P*{iF(PgptizT5VCJP)Aq~}wlUz&7}3e=UFk>YeAVqzKFqxQFExBDRW3HyXa^v-dtWSGn2&+lEh zRqtCUkdq^#9`3yb5-(L;_4k$4H&!SX{Lh7kiM;MY_xI zcFn`bzjBC*4?Q~`)UMkRi85)b;A(Q<^?Y?dyNuLbEJIV|P{o0jC z_-N0^0>-R~Cca{5>t=<9jJ;1JL2;etYT<^+%;i8KA>(TLD#sEOvuVeSb?SEKxZaoF z392%WdPM(mfe}^dJXyadVBYys*k1hbUU5%~uz=GqdGP5w)m5d(<~>fuy={VWKq_{5 zFM4x4q$?fqalfhPigXG#NFGGMe=-<{u+7CDbwhs;`Ge^DOQRIHg=V+(+ON2UMW|vh z2A$vl+{cRy@{&Slv&LQPa?9!T5S7xnUmMI_j}sF0mi~ z9%3kUXakC;RxC45KY`7F6^e!BS6a=QgXpMhcfnV%vgPh-ltWSdbSE7#9D?raue|n_ zdQK=LuSPy6yyXrVK{T#dXMDhNjr!y;yBxoL>=5KAOAv--r2PE;UA^-+jyB(G`0E>Y z=br|&1h3=2Amyd|-A%ruc_c{2KtjloWB!%AiMyTLo!0pCoQ_NlnHDZ*lvJwe-)Gsf zW~ILaZ|i*kVAMyREs-R(t$x0^5SJ69uJr&Vh@@N59r?( zFui3SWEN&aGlzi7r0y2}di4H$hH4K5hQ(>bsXO$YL(p~VUWW^}Sq7p3gQ5goZ{rs# zR|>Dft!h&BgaFyaijvNaRc*UZ>o^%ED5pN^C~vpw+n|_otKB>znI^}E&**I5Nf%Q6 zCzw;=V`+K{T}y&!4wXTp2Vc2HFeNBXIukD6zSMzr0s98h1EF0Ee9WBc&`W%r9i%c< z`qSiu_LZ4CtDvwItL24cY~{>Z;s$TOeKjjLH+i1T`_N zX6_c{pZ$Zsmb+tHlVkqeL3AT)B|ug`#C}E+toT%wGnF~F%LY^8q2Mi)iz1XG-iS-? zw1nGE`&fO#$b!3155tE{le2My=@s-4@c91lRKNni$zT3o52jvg{LUPU{+^3-9$ST6 zUEGRb@2Ye;74q(+x{Sl+X|6q63UXhy1(drKt(J(n23GuQ6|)&RbsLMyd^6k~XTaLW z_CXk6*?HLw#iQyYIY?GjZX!)OOd9=}aB&xF5MD2_fD_!Uofi@9BEN>1lm3{Vq_`T| z=7_a)lg9)4LR(=#1W07-{J4ewmi)3D%O8IdZ#wTcm^KB>L$HEChI4Y~DC z2$FvEU@!nfH9*w79E{$U?x&CHeJFl;Zy0a;)D@2yOKfy zTiLYri(Xb6xf;3>siXF=I~g%8xx-2HdH>eSv^^<+picK@Mjr_S)`_kwj2pg{6(4-m!ORG5%yHwHj$%nnVa)Oz99!ne3PuqW`?kC0#TWVQCPBV$JsY*_wY$-dZnsHB5H2!hq4<6`!>hi`iHkl5IAu_Tbk9I0v?mAf zT7Mhs`crom<#nEF4Z$IDs>i{8|gGqfUp4EQZ3k&m&l@6Gk#Lwp!^qP8h&2 z%v!103vz$pxv>X(?L{^g_j(L;Un99zlBry7+nolG+;AIuH~mT}h|#xdvn`<;{n97`R! zkFl)WdJW;8BE8tgpj%T-VZ3u?UAzRQB6(1WP;-DXKF=T`qIM+wkASQ<=PJOL3*rsMw=M07>5{>px@E>Ci*)Xnu=v9B|Awv~f)m)W)QLTmdT06A4ELs!t=TqphpIPmOvTM*+~iE+-6@KgnJ;0y zb{aE66@kqpK?$wEZ7V`TwgzbM&=o66SK_f8J?W`RS=LQD2SQ?pgV9s%xY0gH8< z`f-M6cVkjj!I5-AU0pT*3SkzQr7~yhy<$Z$G%!>fcTc9##@L=4%| zL$?sHV^-MlEWXTb?Pj5=-^g4n$l1DdGnR*&`!+N4XN@&>Hnzb6ExvS#`DU9+R74w< za;4qGrdR#Gj~t@v?!9}~g-KpO7TuSGjz8dS*f;s|C9@Qovj5(Lp)HQE?pQ@k;-~x2 zM@WfSQIW^MU#9^*Qu0OuI%v9toyFz`xglpf2kAFLqQGB9oqAiy0m^7^6~IU8PmD!t>;~*9%kEC_RV{4h{$@sx@vo?3Xh{&|FhWdzqt6C zg_SigFYnB4Y3YVXNzZS;x4M<40Z>ID-V+S+=a-m#L?PMmP&7$BZUw z^CG@X(@+>P9KV}J$`MTg1|wi9ds6@Yy`4uv9e5=%zuT&4jqA$rdf%yoTp$=2k^bvA zHYE7H2BKkU6)y=v8>do+HtbQWMP*D*jUzA9lsRF83XdJkPby+#uj6(WAmyHe?6?&K z?sBfg^dTH&pQBY`5Sx%t?y~d(gIj=*_?PIJR~Pv1T5=iZw$BvsgW zy+w!-(PyLJ)YLxDosp;)IvNUIUaEjVQY?;CGO>MS<2Hnc+xH}Ez{YpMTy%hAbf0>l z>@ze}s9POc?Y!WGyyEO2o_4$`2QgXv@cH@;n&_nJmzF1{H9bg5Og)U^)UH5uK_!> zlmu+AP)y{T>!9p#k-^Xm6W7DLv}O~_8nzSPqjj9^ek@u0Ma#Hm|z z>2VhTUiJD3LLeM84D`_Sq!U-~Ee7}`AfcD_mdyK)-FR;-9BPB4BDI|p#;G#~8PbQ_!M z3OnCu5&wbE{u>jnG&%q(tX98lER&kKfz)ggKG6!*XIiM z#Z$aFGv(S z@**p1N^m>4HQUP*q!|JN$nxkFF zjZ39`5-B_BOUmqhy0v#L3%95^%AEDO6rasdT?hWopj{&NjPU2_ixA-zTD7RRC%1|pY( zW?$Em2X%C>SO{1gSIMq`A@CtF@s}AHNbAra=w2z|;N+xxgE=`onk~BRywP z7U1akuWaDNp9WA_NKppz24@shROtf9#Gl-6GsFiXkALg3Di)!d%DCg}cF)I~3vM6k zbl3S&$D6}Ei=d=6gwZJOHoR9rw~&L|=*uZQ9nq9|f(LcmKlnX%^Kt-sLpG%QE^nY+ zR*ICQHzbFB_Kjf487sZ;8Wms@38GbkZmD#d{)RMv7l`jB6Bpi%L2} z9`Fvp!pR?SdT2?hW7)_Gn}9%Rhi{+jnr_`6uZgm?_-hL_@X(aH5(4AZ6Sg(lUsUt? zX7aQg+u7BrJA~Qn&m66;pALCjw3buq;_qm}KZqJGXw&Co-4sZ}8MOXnEd^)IX>GO+y$rgTd@RyI=b39c@ z&dthGTMS#H!|+s-`}DdRIbaStxUfxNZlb!Pd9^|e*$VjbK6bp(px}zd-Yq%`*jl=b z%9D6=H4U|nG5_Ui=ii4V;0WvqA4wNE4e!oEzsO6_M|_Yj(>7dh7BYoc)O z)}(sze*#KzSq*{6&d0==#jU=drbC7Re3LLqeWjxoXq>pSgi3gFP^71ViS0LSE92uz znUF{^I0rN%vCK70oI+nX+2Ix1pYy`t`$O=D+eRlDVRj-uVV`QBWL)RJ>4BGG{MoCwgYa&AaV)N-a-_@sXq zFg<5>6|;_llK1r#2Zx1=cDngI;B>!*Xf>W{3n&!vPEyX!0p=#?^Q&E$?I&IReOhVj zJ6!QR_N9e{yohroj|^Z~^VT$pw}89Z3^iN^NjJa0Z_@%KM|k4hTcgnYcF_u(oHcEYuo=4b8l-nvphW{CXdA(C!04<>BUMoGyv(#0 ze=mpe@$b+h_c8kJr68Rk4F%6|aPj+Rodm|;H#)d9Tx54}r!jJMR{L#u|I0LqsOKi< zWxt)bbmSFa!cmrg@ijcqK1O4Z{RDypbDD9w+NH#+;(>KfK)}}3BcbV+aqm= z$?xZU(p2Oka1g&9r%+JV?sB3tikjWLFYeNYXD|hEuKv=Me ziHU)<2g{xP(mU+JuS^VHyigiW?;9<%QY^4Yi2@0AHK|6o+Z*b=$12_JbJmcd;pYYe zB)oZK+oROh+UgP0M{AEsr8rZ31et+Gt-&l{gA3gLndAB=vt~NYN$~B?^k{ZWaGwZO z{kj!{AK&xJRSCNT`z@9FIHPBak$&UK5B5Sr?%%a7+>1*vJZen z&Zh8ZRPEhr3=Pek`JF*oepn*2svm~f^8hsu@|869ZEE_M1`2wB9lbkxdyDZts|7u1 zJCOxti6~J0*&4yvHs5o_avm~%NEszrcC`|v+?Os@yTzdhZgrEWEe`%_Ev0N@^A^KE^S2@ALCqobOZ{g36~emU9(_h=QHia0*)Z zly?Xp`$0ghtQgopTcTlq=JI@Z^>l3WJ;GSa2?UF{I48(H+KEpH8Ly$mj}7LgZe4X$ zghc?PN0f*$wGb-04Oeqt{)AO%-8|waZa73)n4h5~2Q@?cPD^kdzs)Su`vs9H3Khho zku`q)c_dpAb?3R*>Bva9gm0AlSozNwvK`M}V37O`sh!O|L z9}l;jfDly2QQK z+1|SD!glCjbDct++CW9#hW7~uUU_4?&q5W0!@?xK3J|1P`J)$vu>^`9N+mlI*~CPT zrHLmlT$86)0x>W3N-{Rc;ntYHeUp#mO8WW1X764}ma>tDxl8I-B9@=Mlae!%NTr3J zbE67zVzsrr1LwLq@>$9V1&VyA7R89mcjhcB&%Da8|6<+bV}0IGUS{~-H)vs&foSKp z0C5G>x?Bu@kjYe98U2K(;h=}ExvgazeYuZh%B>nC7S)yQ$AR6T8Tr`0N?^^`5F&bn zc2r>`wBv`h&?bo`_Q#G(M#+iTpiNut_gwaR1y5tHVPj9%%(q z6;>b@{2LFEjY@;f)1qDtU(9uslEmXkJTHuvTdMlIVPN>l?nHsv_j6+6;>iZ}UIGh& z^ubY43qvhoC?2=d3F8kzpeGXPL4>5tPrk$-04;0=n_zf;YHJeT@M!F4y*>)mC2Zm~ z3q?Pt!4P=+d9(w`M6LS;qt&X?xx$gYz-u7lP*-#pq7vYb)7ORzGj zyF9_3IZ|A%S3fr{sBimM2BRw&%D>!3GY14s`5+2% zN-ikgnsr+8<~_BORCTI~wYBvrRh!e9d!VH@&BiA7_F^U1UoSN{^)@GG`tN7$ow^Y_F~}UX>vuvFsk_$e36DXCuT0oqm!%dEQuv<|0Mz8 zKgSkjcj_rSynM-$zFaG5~Ec%hV j|9A95U^9RR;UE)du`ldy^_UPgZBTfsB2)a>=-vMS9RhM$ diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index 08b7073c3d..daa7102b79 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -47,7 +47,7 @@ There are four settings available: - `Set status on note` -> turns on and off this integrator. - `Note shortname` -> Which status shortname should be set automatically (Case sensitive). - `Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). -- `Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Equality` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you only publish the workfile subset. +- `Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Condition` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you only publish the workfile subset. ![Integrate Kitsu Note project settings](assets/integrate_kitsu_note_settings.png) From d8360b5b19cad2110efdc71a9c72d007c2c8b927 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 8 Mar 2023 12:11:09 +0100 Subject: [PATCH 22/59] Made changes to resolve conflicts with develop. Changes how publisshed families are accessed. --- .../plugins/publish/integrate_kitsu_note.py | 96 +++++++++---------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 2c85a5f70b..3c3607a987 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -73,56 +73,54 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): if self.set_status_note and allow_status_change: kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname - families = set() - for instance in context: - if instance.data.get('publish'): - families.add(instance.data['family']) + families = set( + instance.data.get('kitsu_task') + for instance in context + if instance.data.get('publish') + ) - # Get note status, by default uses the task status for the note - # if it is not specified in the configuration - kitsu_task = context.data["kitsu_task"] - shortname = kitsu_task["task_status"]["short_name"].upper() - note_status = kitsu_task["task_status_id"] - if self.set_status_note and next( - ( - False - for status_except in self.status_exceptions - if shortname == status_except["short_name"].upper() - and status_except["condition"] == "equal" - or - shortname != status_except["short_name"].upper() - and status_except["condition"] == "not_equal" - ), - True, - ) and next( - ( - True - for family in families - if next( - ( - False - for family_req in self.family_requirements - if family_req['condition'] == 'equal' - and family_req['family'].lower() != family - or - family_req['condition'] == 'not_equal' - and family_req['family'].lower() == family - ), - True, - ) - ), - False, - ): - kitsu_status = gazu.task.get_task_status_by_short_name( - self.note_status_shortname - ) - if kitsu_status: - note_status = kitsu_status - self.log.info("Note Kitsu status: {}".format(note_status)) - else: - self.log.info( - "Cannot find {} status. The status will not be " - "changed!".format(self.note_status_shortname) + for instance in context: + kitsu_task = instance.data.get("kitsu_task") + if not kitsu_task: + continue + + # Get note status, by default uses the task status for the note + # if it is not specified in the configuration + kitsu_task = context.data["kitsu_task"] + shortname = kitsu_task["task_status"]["short_name"].upper() + note_status = kitsu_task["task_status_id"] + if self.set_status_note and next( + ( + False + for status_except in self.status_exceptions + if shortname == status_except["short_name"].upper() + and status_except["condition"] == "equal" + or + shortname != status_except["short_name"].upper() + and status_except["condition"] == "not_equal" + ), + True, + ) and next( + ( + True + for family in families + if next( + ( + False + for family_req in self.family_requirements + if family_req['condition'] == 'equal' + and family_req['family'].lower() != family + or + family_req['condition'] == 'not_equal' + and family_req['family'].lower() == family + ), + True, + ) + ), + False, + ): + kitsu_status = gazu.task.get_task_status_by_short_name( + self.note_status_shortname ) if kitsu_status: note_status = kitsu_status From 83aabf4c2bfed63cbaa63fab3de14d5b53668a14 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 8 Mar 2023 12:15:00 +0100 Subject: [PATCH 23/59] Linted --- .../plugins/publish/integrate_kitsu_note.py | 71 +++++++++++-------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 3c3607a987..f394a3d04b 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -55,6 +55,10 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): kitsu_task = instance.data.get("kitsu_task") if kitsu_task is None: continue + # Get comment text body + publish_comment = context.data.get("comment") + if not publish_comment: + self.log.info("Comment is not set.") # Get note status, by default uses the task status for the note # if it is not specified in the configuration @@ -74,9 +78,9 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname families = set( - instance.data.get('kitsu_task') + instance.data.get("kitsu_task") for instance in context - if instance.data.get('publish') + if instance.data.get("publish") ) for instance in context: @@ -89,35 +93,37 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): kitsu_task = context.data["kitsu_task"] shortname = kitsu_task["task_status"]["short_name"].upper() note_status = kitsu_task["task_status_id"] - if self.set_status_note and next( - ( - False - for status_except in self.status_exceptions - if shortname == status_except["short_name"].upper() - and status_except["condition"] == "equal" - or - shortname != status_except["short_name"].upper() - and status_except["condition"] == "not_equal" - ), - True, - ) and next( - ( - True - for family in families - if next( - ( - False - for family_req in self.family_requirements - if family_req['condition'] == 'equal' - and family_req['family'].lower() != family - or - family_req['condition'] == 'not_equal' - and family_req['family'].lower() == family - ), - True, - ) - ), - False, + if ( + self.set_status_note + and next( + ( + False + for status_except in self.status_exceptions + if shortname == status_except["short_name"].upper() + and status_except["condition"] == "equal" + or shortname != status_except["short_name"].upper() + and status_except["condition"] == "not_equal" + ), + True, + ) + and next( + ( + True + for family in families + if next( + ( + False + for family_req in self.family_requirements + if family_req["condition"] == "equal" + and family_req["family"].lower() != family + or family_req["condition"] == "not_equal" + and family_req["family"].lower() == family + ), + True, + ) + ), + False, + ) ): kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname @@ -147,6 +153,9 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): ) kitsu_comment = gazu.task.add_comment( kitsu_task, note_status, comment=publish_comment + instance.data["kitsu_task"], + note_status, + comment=publish_comment, ) instance.data["kitsu_comment"] = kitsu_comment From 2022a38c650bf6dcd5603c88ecbebd09d176b2b0 Mon Sep 17 00:00:00 2001 From: Sharkitty <81646000+Sharkitty@users.noreply.github.com> Date: Wed, 15 Mar 2023 09:20:17 +0000 Subject: [PATCH 24/59] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adjustment to documentation, and families set declaration Co-authored-by: FΓ©lix David --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 4 ++-- website/docs/module_kitsu.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index f394a3d04b..0bb2a63fea 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -77,11 +77,11 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): if self.set_status_note and allow_status_change: kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname - families = set( + families = { instance.data.get("kitsu_task") for instance in context if instance.data.get("publish") - ) + } for instance in context: kitsu_task = instance.data.get("kitsu_task") diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index daa7102b79..9a85f83e3f 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -44,10 +44,10 @@ Task status can be automatically set during publish thanks to `Integrate Kitsu N `Admin -> Studio Settings -> Project Settings -> Kitsu -> Integrate Kitsu Note`. There are four settings available: -- `Set status on note` -> turns on and off this integrator. +- `Set status on note` -> Turns on and off this integrator. - `Note shortname` -> Which status shortname should be set automatically (Case sensitive). - `Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). -- `Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Condition` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you only publish the workfile subset. +- `Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Condition` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you publish the workfile subset only. ![Integrate Kitsu Note project settings](assets/integrate_kitsu_note_settings.png) From 5ca5498b03bb1a88564b43e09fa4e660111614ec Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Tue, 21 Mar 2023 17:33:50 +0100 Subject: [PATCH 25/59] Changed family requirement check based on discussions --- .../plugins/publish/integrate_kitsu_note.py | 79 ++++++------------- 1 file changed, 23 insertions(+), 56 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 0bb2a63fea..366e70934f 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -53,12 +53,8 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): continue kitsu_task = instance.data.get("kitsu_task") - if kitsu_task is None: + if not kitsu_task: continue - # Get comment text body - publish_comment = context.data.get("comment") - if not publish_comment: - self.log.info("Comment is not set.") # Get note status, by default uses the task status for the note # if it is not specified in the configuration @@ -74,57 +70,31 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): allow_status_change = False break - if self.set_status_note and allow_status_change: - kitsu_status = gazu.task.get_task_status_by_short_name( - self.note_status_shortname - families = { - instance.data.get("kitsu_task") - for instance in context - if instance.data.get("publish") - } + if allow_status_change: + # Get families + families = { + instance.data.get("kitsu_task") + for instance in context + if instance.data.get("publish") + } - for instance in context: - kitsu_task = instance.data.get("kitsu_task") - if not kitsu_task: - continue + # Check if any family requirement is met + for family_requirement in self.family_requirements: + condition = family_requirement["condition"] == "equal" - # Get note status, by default uses the task status for the note - # if it is not specified in the configuration - kitsu_task = context.data["kitsu_task"] - shortname = kitsu_task["task_status"]["short_name"].upper() - note_status = kitsu_task["task_status_id"] - if ( - self.set_status_note - and next( - ( - False - for status_except in self.status_exceptions - if shortname == status_except["short_name"].upper() - and status_except["condition"] == "equal" - or shortname != status_except["short_name"].upper() - and status_except["condition"] == "not_equal" - ), - True, - ) - and next( - ( - True - for family in families - if next( - ( - False - for family_req in self.family_requirements - if family_req["condition"] == "equal" - and family_req["family"].lower() != family - or family_req["condition"] == "not_equal" - and family_req["family"].lower() == family - ), - True, + for family in families: + match = ( + family_requirement["short_name"].lower() == family ) - ), - False, - ) - ): + if match and not condition or condition and not match: + allow_status_change = True + break + + if allow_status_change: + break + + # Set note status + if self.set_status_note and allow_status_change: kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname ) @@ -153,9 +123,6 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): ) kitsu_comment = gazu.task.add_comment( kitsu_task, note_status, comment=publish_comment - instance.data["kitsu_task"], - note_status, - comment=publish_comment, ) instance.data["kitsu_comment"] = kitsu_comment From 109435fee281acd7be8bd2f2a67573e4221e8761 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Tue, 21 Mar 2023 17:48:01 +0100 Subject: [PATCH 26/59] Fixed kitsu project settings schema, updated documentation screenshot --- .../projects_schema/schema_project_kitsu.json | 1 - .../assets/integrate_kitsu_note_settings.png | Bin 44847 -> 46673 bytes 2 files changed, 1 deletion(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index ba77f2b471..0a3a5e6e7b 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -127,7 +127,6 @@ "label": "Custom comment" } ] - } } ] } diff --git a/website/docs/assets/integrate_kitsu_note_settings.png b/website/docs/assets/integrate_kitsu_note_settings.png index fd055942d023e2ffc12fc508cd7079eb834045c3..6f76556afa54b4a1cd946ffb78d200ec3cd3e3b1 100644 GIT binary patch literal 46673 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%0D3V?)tF)Lx2^;H(ZQbbO&WO=KC?o7RUlAm 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
  • bzki{Py{Pds_+NLrzF>l&iL#!pA0lu=Pb|*x!3Ya10B1s6(fwHio`Y3yaj;;$ zSpO;pTMD}L!oUc5B$$9UZ>Xry9CqnoQ2#JDgmUBB-mIjn*kxAm2^h(8Qz)&95RJ%DcAH$#yOlU0il?itP#kFet zVX0*Pm=a~yqVi{q9+Fl9tPMKgOo85tq9;V{?&`dqQ`T_{?}s!LI$E-1{V_a z<;#vsPHSi9RNbM=V2O=UwH_n>B~g+y?dA_nO2E_?7kfx4cduBi`Qp(@c~BMEkV-F~ zfD&`QFqPA0o97ZHry$dsucNJo_g`)@$5PY9iUE&<7g|Sr#a712@4Ag-OuGxsMniHZ za4v83HW^&~xAgsKP5-;Tzc(qC^g2od zK}7GHodh!q(_Un%%2`c(4%-QUK|t6-GYB-hX>80?E-6{HzFg@zShZX1)@Cb8*j#A< zEYsoEXYzq1Z$JS#pE8v?TZ(O0VGX*OSy`A}-DqjCm)FfG>3-fe>b3es2@(G-N5Ad) z_BPVx*{xychLzNT3j^rj;2`{0^r~Mqs____v?Bt~)45@brV6etg}~3FPX?6OHh8Xy zNZe@{Yt8f1Z5_t7K{JJ+@qrYAGlgmK645k`RLJrziIew=bPCS1VtXxwN^+~qXe!SY z9H66D?s6$TRuNhlloQ(D>^CU&X3jfjxY{P#c}GtV14jlbqfM*J);pwq_kNCh%zeM? zw>9603)+@u30@Sg*L7Iu!|(@vIEuwIBx}R)`a-uYDo1nqoi%yELvc9G7Oh)N4sYyTSoVD7{H*p-T zcm*2c>PA~IoC12%sZjD4zRTru`gwm{kh10`m)m;+cu3HWnQzCu#%xhI9lNsnISh)> z;5DY@+duFKr(g`75W81oOUbU1`h=S4d|RD-BIsCh_2TB>@u||L`zh!zb*|&Odu6^W*5!Z zBAKf0Xl&d&yTv@z4M@bA(OTBhVG}P|Db6>Gi}6;o^wauIviqxtC#htc+F0{nx6foB z=IG^5ht=Yv0WEq-fLZ1V`)d_wO5C@bn#ZXlX~6M#jT-yj7b;j8|1>K2VR>2-ura!N zF%DiSP;;gS(yI@S5@&}en4@7q^716BtE-@N`gHpe7Z(b%ze<(|1?|9^h1bZ5HTLep zdZ*~2e(mH`7{FBuGb|tpU?~FC8`{bg zto1Fg2zD=LkH`0J+z|^Kd9cl=01o1m?Fr?N=C*O{^9^P+1=HKW;c;uaHb~z~4!9=@ zSS1Z8$Og-kR&0W^_Z-)Ji4uAs?nQl~8YBFv6@}c0nk@=Dd$44$276RwQDXRUcuAK4 zW+yRPOjqGVx-t^_R!Uen?qZOyEWx1sLjdHGo9E;pHpMr@{*_6{uLwz>hi&9 zxI}kbKmUL#T{(Jkl7+s=d8wkv&--X`kJGUO2g{UofO)?!#9vCA?UY$4c(0kMp z0}Ea`+z(i(CzZjE*Usiw;%1gBaqqISo@A;f7Ou&0bDG#eX*c1eR#d&(#^;Il+^Nxk;P=(h**;EW8$UFEG)$QBYdDJF|ZB2(LQ@z&l zvzTqIsOw$exrmz9zkt)U<#gm**Dkrb1y09??t=4*s{&qV6!*3?73Y&X}NFqIrsE^+$uhWrSF&( zanVkX(9SLVT8H#kslnCQGUHmL)JX{B-r4TW_NJIE9rzUs=m|qExgD0ot3EpLw&?9> z2;@8AP5wyK@{d%{#zH4zm>yUF*%X7Vl2LgdacjE-H zgGl-LXXPHuBp0&tx!l~>q?a8>o|>U-o~d}L2?%JzNgxou+_WZkoTufdS|<39OPpTo zo%h1o?|)pc7wRBwxVJR^EGSq~${<0C3<5E?h{k$73)el6k#TN3x?nx1BtN@GYY!v% zg?tPyOyKh%Lh%!)!MBjt6e{2wq|F*i>|k%s*#K@N1R{$6vlo6#kqxpiMtpfoNkcJT I!94Uo0HuA#d;kCd literal 44847 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 BT7Uom From e9eb09e100d990e5a6d8648ff32df0d3e7ec4969 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 12:58:33 +0000 Subject: [PATCH 27/59] Initial working version --- .../maya/plugins/publish/collect_review.py | 23 +++-- openpype/lib/execute.py | 7 ++ openpype/plugins/publish/extract_burnin.py | 4 + openpype/scripts/otio_burnin.py | 87 +++++++++++++++++-- 4 files changed, 109 insertions(+), 12 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 80fd5b0dbd..3d3ee09eed 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -146,11 +146,24 @@ class CollectReview(pyblish.api.InstancePlugin): ) # Collect focal length. - data = { - "cameraFocalLength": cmds.getAttr(camera + ".focalLength") - } + #Refactor to lib or use available lib method. + plug = "{0}.focalLength".format(camera) + focal_length = None + if not cmds.listConnections(plug, destination=False, source=True): + # Static. + focal_length = cmds.getAttr(plug) + else: + # Dynamic. + start = instance.data["frameStart"] + end = instance.data["frameEnd"] + 1 + focal_length = [ + cmds.getAttr(plug, time=t) for t in range(int(start), int(end)) + ] + + key = "focalLength" + instance.data[key] = focal_length try: - instance.data["customData"].update(data) + instance.data["burninDataMembers"].append(key) except KeyError: - instance.data["customData"] = data + instance.data["burninDataMembers"] = [key] diff --git a/openpype/lib/execute.py b/openpype/lib/execute.py index 759a4db0cb..5ba62f177f 100644 --- a/openpype/lib/execute.py +++ b/openpype/lib/execute.py @@ -8,6 +8,8 @@ import tempfile from .log import Logger from .vendor_bin_utils import find_executable +from .openpype_version import is_running_from_build + # MSDN process creation flag (Windows only) CREATE_NO_WINDOW = 0x08000000 @@ -196,6 +198,11 @@ def run_openpype_process(*args, **kwargs): # Skip envs that can affect OpenPype process # - fill more if you find more env = clean_envs_for_openpype_process(os.environ) + + # Add OpenPype version if we are running from build. + if not is_running_from_build(): + env.pop("OPENPYPE_VERSION", None) + return run_subprocess(args, env=env, **kwargs) diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py index f113e61bb0..de876c8486 100644 --- a/openpype/plugins/publish/extract_burnin.py +++ b/openpype/plugins/publish/extract_burnin.py @@ -254,6 +254,10 @@ class ExtractBurnin(publish.Extractor): # Add context data burnin_data. burnin_data["custom"] = custom_data + # Add data members. + for key in instance.data.get("burninDataMembers", []): + burnin_data[key] = instance.data[key] + # Add source camera name to burnin data camera_name = repre.get("camera_name") if camera_name: diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index cb4646c099..bb7a208103 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -4,8 +4,10 @@ import re import subprocess import platform import json -import opentimelineio_contrib.adapters.ffmpeg_burnins as ffmpeg_burnins +import tempfile +from string import Formatter +import opentimelineio_contrib.adapters.ffmpeg_burnins as ffmpeg_burnins from openpype.lib import ( get_ffmpeg_tool_path, get_ffmpeg_codec_args, @@ -23,7 +25,7 @@ FFMPEG = ( ).format(ffmpeg_path) DRAWTEXT = ( - "drawtext=fontfile='%(font)s':text=\\'%(text)s\\':" + "drawtext@'%(label)s'=fontfile='%(font)s':text=\\'%(text)s\\':" "x=%(x)s:y=%(y)s:fontcolor=%(color)s@%(opacity).1f:fontsize=%(size)d" ) TIMECODE = ( @@ -39,6 +41,34 @@ TIMECODE_KEY = "{timecode}" SOURCE_TIMECODE_KEY = "{source_timecode}" +def convert_list_to_cmd(list_to_convert, fps, label=""): + path = None + #need to clean up temp file when done + with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: + for i, value in enumerate(list_to_convert): + seconds = i / fps + + # Escape special character + value = str(value).replace(":", "\\:") + + filter = "drawtext" + if label: + filter += "@" + label + + line = ( + "{start} {filter} reinit text='{value}';" + "\n".format(start=seconds, filter=filter, value=value) + ) + + f.write(line) + f.flush() + path = f.name + path = path.replace("\\", "/") + path = path.replace(":", "\\:") + + return "sendcmd=f='{}'".format(path) + + def _get_ffprobe_data(source): """Reimplemented from otio burnins to be able use full path to ffprobe :param str source: source media file @@ -144,7 +174,7 @@ class ModifiedBurnins(ffmpeg_burnins.Burnins): self.options_init.update(options_init) def add_text( - self, text, align, frame_start=None, frame_end=None, options=None + self, text, align, frame_start=None, frame_end=None, options=None, cmd="" ): """ Adding static text to a filter. @@ -165,7 +195,13 @@ class ModifiedBurnins(ffmpeg_burnins.Burnins): if frame_end is not None: options["frame_end"] = frame_end - self._add_burnin(text, align, options, DRAWTEXT) + draw_text = DRAWTEXT + if cmd: + draw_text = "{}, {}".format(cmd, DRAWTEXT) + + options["label"] = align + + self._add_burnin(text, align, options, draw_text) def add_timecode( self, align, frame_start=None, frame_end=None, frame_start_tc=None, @@ -501,7 +537,7 @@ def burnins_from_data( if not value: continue - if isinstance(value, (dict, list, tuple)): + if isinstance(value, (dict, tuple)): raise TypeError(( "Expected string or number type." " Got: {} - \"{}\"" @@ -573,8 +609,43 @@ def burnins_from_data( burnin.add_timecode(*args) continue - text = value.format(**data) - burnin.add_text(text, align, frame_start, frame_end) + cmd = "" + text = None + keys = [i[1] for i in Formatter().parse(value) if i[1] is not None] + list_to_convert = [] + + # Warn about nested dictionary support for lists. Ei. we dont support + # it. + if "[" in "".join(keys): + print( + "We dont support converting nested dictionaries to lists," + " so skipping {}".format(value) + ) + else: + for key in keys: + data_value = data[key] + + # Multiple lists are not supported. + if isinstance(data_value, list) and list_to_convert: + raise ValueError( + "Found multiple lists to convert, which is not " + "supported: {}".format(value) + ) + + if isinstance(data_value, list): + print("Found list to convert: {}".format(data_value)) + for v in data_value: + data[key] = v + list_to_convert.append(value.format(**data)) + + if list_to_convert: + text = list_to_convert[0] + cmd = convert_list_to_cmd(list_to_convert, 25.0, label=align)# need to fetch fps properly + print("cmd: " + cmd) + else: + text = value.format(**data) + print(text) + burnin.add_text(text, align, frame_start, frame_end, cmd=cmd) ffmpeg_args = [] if codec_data: @@ -613,6 +684,8 @@ if __name__ == "__main__": with open(in_data_json_path, "r") as file_stream: in_data = json.load(file_stream) + print(json.dumps(in_data, indent=4, sort_keys=True)) + burnins_from_data( in_data["input"], in_data["output"], From 583fecd4009003681fb6cc535aecdbe641a66022 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 22 Mar 2023 14:37:59 +0100 Subject: [PATCH 28/59] Fixes and adjustments based on reviews --- .../plugins/publish/integrate_kitsu_note.py | 18 ++-- .../defaults/project_settings/kitsu.json | 6 +- .../projects_schema/schema_project_kitsu.json | 97 ++++++++++-------- .../assets/integrate_kitsu_note_settings.png | Bin 46673 -> 48874 bytes website/docs/module_kitsu.md | 4 +- 5 files changed, 69 insertions(+), 56 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 366e70934f..a5253d7878 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -14,8 +14,10 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): # status settings set_status_note = False note_status_shortname = "wfa" - status_conditions = list() - family_requirements = list() + status_change_conditions = { + "status_conditions": [], + "family_requirements": [], + } # comment settings custom_comment_template = { @@ -63,7 +65,7 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): # Check if any status condition is not met allow_status_change = True - for status_cond in self.status_conditions: + for status_cond in self.status_change_conditions["status_conditions"]: condition = status_cond["condition"] == "equal" match = status_cond["short_name"].upper() == shortname if match and not condition or condition and not match: @@ -73,20 +75,22 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): if allow_status_change: # Get families families = { - instance.data.get("kitsu_task") + instance.data.get("family") for instance in context if instance.data.get("publish") } + allow_status_change = False + # Check if any family requirement is met - for family_requirement in self.family_requirements: + for family_requirement in self.status_change_conditions["family_requirements"]: condition = family_requirement["condition"] == "equal" for family in families: match = ( - family_requirement["short_name"].lower() == family + family_requirement["family"].lower() == family ) - if match and not condition or condition and not match: + if match and condition or not condition and not match: allow_status_change = True break diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index 32c6c253c7..59a36d8b97 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -8,8 +8,10 @@ "IntegrateKitsuNote": { "set_status_note": false, "note_status_shortname": "wfa", - "status_conditions": [], - "family_requirements": [], + "status_change_conditions": { + "status_conditions": [], + "family_requirements": [] + }, "custom_comment_template": { "enabled": false, "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index 0a3a5e6e7b..8aeed00542 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -54,55 +54,62 @@ "label": "Note shortname" }, { - "type": "list", - "key": "status_conditions", - "label": "Status conditions", - "object_type": { - "type": "dict", - "key": "conditions_dict", - "children": [ - { - "type": "enum", - "key": "condition", - "label": "Condition", - "enum_items": [ - {"equal": "Equal"}, - {"not_equal": "Not equal"} + "type": "dict", + "collapsible": true, + "key": "status_change_conditions", + "label": "Status change conditions", + "children": [ + { + "type": "list", + "key": "status_conditions", + "label": "Status conditions", + "object_type": { + "type": "dict", + "key": "condition_dict", + "children": [ + { + "type": "enum", + "key": "condition", + "label": "Condition", + "enum_items": [ + {"equal": "Equal"}, + {"not_equal": "Not equal"} + ] + }, + { + "type": "text", + "key": "short_name", + "label": "Short name" + } ] - }, - { - "type": "text", - "key": "short_name", - "label": "Short name" } - ] - }, - "label": "Status shortname" - }, - { - "type": "list", - "key": "family_requirements", - "label": "Family requirements", - "object_type": { - "type": "dict", - "key": "requirement_dict", - "children": [ - { - "type": "enum", - "key": "condition", - "label": "Condition", - "enum_items": [ - {"equal": "Equal"}, - {"not_equal": "Not equal"} + }, + { + "type": "list", + "key": "family_requirements", + "label": "Family requirements", + "object_type": { + "type": "dict", + "key": "requirement_dict", + "children": [ + { + "type": "enum", + "key": "condition", + "label": "Condition", + "enum_items": [ + {"equal": "Equal"}, + {"not_equal": "Not equal"} + ] + }, + { + "type": "text", + "key": "family", + "label": "Family" + } ] - }, - { - "type": "text", - "key": "family", - "label": "Family" } - ] - } + } + ] }, { "type": "dict", diff --git a/website/docs/assets/integrate_kitsu_note_settings.png b/website/docs/assets/integrate_kitsu_note_settings.png index 6f76556afa54b4a1cd946ffb78d200ec3cd3e3b1..9c59f0bf5cc9a748de1a8b66b248f539ee8014b5 100644 GIT binary patch literal 48874 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%0D3V?)tF)Lx2^;H(ZQbbO&WO=KC?o7RUlAm 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

  • bzki{Py{Pds_+NLrzF>l&iL#!pA0lu=Pb|*x!3Ya10B1s6(fwHio`Y3yaj;;$ zSpO;pTMD}L!oUc5B$$9UZ>Xry9CqnoQ2#JDgmUBB-mIjn*kxAm2^h(8Qz)&95RJ%DcAH$#yOlU0il?itP#kFet zVX0*Pm=a~yqVi{q9+Fl9tPMKgOo85tq9;V{?&`dqQ`T_{?}s!LI$E-1{V_a z<;#vsPHSi9RNbM=V2O=UwH_n>B~g+y?dA_nO2E_?7kfx4cduBi`Qp(@c~BMEkV-F~ zfD&`QFqPA0o97ZHry$dsucNJo_g`)@$5PY9iUE&<7g|Sr#a712@4Ag-OuGxsMniHZ za4v83HW^&~xAgsKP5-;Tzc(qC^g2od zK}7GHodh!q(_Un%%2`c(4%-QUK|t6-GYB-hX>80?E-6{HzFg@zShZX1)@Cb8*j#A< zEYsoEXYzq1Z$JS#pE8v?TZ(O0VGX*OSy`A}-DqjCm)FfG>3-fe>b3es2@(G-N5Ad) z_BPVx*{xychLzNT3j^rj;2`{0^r~Mqs____v?Bt~)45@brV6etg}~3FPX?6OHh8Xy zNZe@{Yt8f1Z5_t7K{JJ+@qrYAGlgmK645k`RLJrziIew=bPCS1VtXxwN^+~qXe!SY z9H66D?s6$TRuNhlloQ(D>^CU&X3jfjxY{P#c}GtV14jlbqfM*J);pwq_kNCh%zeM? zw>9603)+@u30@Sg*L7Iu!|(@vIEuwIBx}R)`a-uYDo1nqoi%yELvc9G7Oh)N4sYyTSoVD7{H*p-T zcm*2c>PA~IoC12%sZjD4zRTru`gwm{kh10`m)m;+cu3HWnQzCu#%xhI9lNsnISh)> z;5DY@+duFKr(g`75W81oOUbU1`h=S4d|RD-BIsCh_2TB>@u||L`zh!zb*|&Odu6^W*5!Z zBAKf0Xl&d&yTv@z4M@bA(OTBhVG}P|Db6>Gi}6;o^wauIviqxtC#htc+F0{nx6foB z=IG^5ht=Yv0WEq-fLZ1V`)d_wO5C@bn#ZXlX~6M#jT-yj7b;j8|1>K2VR>2-ura!N zF%DiSP;;gS(yI@S5@&}en4@7q^716BtE-@N`gHpe7Z(b%ze<(|1?|9^h1bZ5HTLep zdZ*~2e(mH`7{FBuGb|tpU?~FC8`{bg zto1Fg2zD=LkH`0J+z|^Kd9cl=01o1m?Fr?N=C*O{^9^P+1=HKW;c;uaHb~z~4!9=@ zSS1Z8$Og-kR&0W^_Z-)Ji4uAs?nQl~8YBFv6@}c0nk@=Dd$44$276RwQDXRUcuAK4 zW+yRPOjqGVx-t^_R!Uen?qZOyEWx1sLjdHGo9E;pHpMr@{*_6{uLwz>hi&9 zxI}kbKmUL#T{(Jkl7+s=d8wkv&--X`kJGUO2g{UofO)?!#9vCA?UY$4c(0kMp z0}Ea`+z(i(CzZjE*Usiw;%1gBaqqISo@A;f7Ou&0bDG#eX*c1eR#d&(#^;Il+^Nxk;P=(h**;EW8$UFEG)$QBYdDJF|ZB2(LQ@z&l zvzTqIsOw$exrmz9zkt)U<#gm**Dkrb1y09??t=4*s{&qV6!*3?73Y&X}NFqIrsE^+$uhWrSF&( zanVkX(9SLVT8H#kslnCQGUHmL)JX{B-r4TW_NJIE9rzUs=m|qExgD0ot3EpLw&?9> z2;@8AP5wyK@{d%{#zH4zm>yUF*%X7Vl2LgdacjE-H zgGl-LXXPHuBp0&tx!l~>q?a8>o|>U-o~d}L2?%JzNgxou+_WZkoTufdS|<39OPpTo zo%h1o?|)pc7wRBwxVJR^EGSq~${<0C3<5E?h{k$73)el6k#TN3x?nx1BtN@GYY!v% zg?tPyOyKh%Lh%!)!MBjt6e{2wq|F*i>|k%s*#K@N1R{$6vlo6#kqxpiMtpfoNkcJT I!94Uo0HuA#d;kCd diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index 9a85f83e3f..05cff87fcc 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -46,8 +46,8 @@ Task status can be automatically set during publish thanks to `Integrate Kitsu N There are four settings available: - `Set status on note` -> Turns on and off this integrator. - `Note shortname` -> Which status shortname should be set automatically (Case sensitive). -- `Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). -- `Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Condition` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you publish the workfile subset only. +- `Status change conditions - Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). +- `Status change conditions - Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Condition` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you publish the workfile subset only. ![Integrate Kitsu Note project settings](assets/integrate_kitsu_note_settings.png) From 3af273679011d230d48aaa97a8d8468e69944c70 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 22 Mar 2023 14:38:42 +0100 Subject: [PATCH 29/59] linted --- .../kitsu/plugins/publish/integrate_kitsu_note.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index a5253d7878..6a1b09dde1 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -65,7 +65,9 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): # Check if any status condition is not met allow_status_change = True - for status_cond in self.status_change_conditions["status_conditions"]: + for status_cond in self.status_change_conditions[ + "status_conditions" + ]: condition = status_cond["condition"] == "equal" match = status_cond["short_name"].upper() == shortname if match and not condition or condition and not match: @@ -83,13 +85,13 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): allow_status_change = False # Check if any family requirement is met - for family_requirement in self.status_change_conditions["family_requirements"]: + for family_requirement in self.status_change_conditions[ + "family_requirements" + ]: condition = family_requirement["condition"] == "equal" for family in families: - match = ( - family_requirement["family"].lower() == family - ) + match = family_requirement["family"].lower() == family if match and condition or not condition and not match: allow_status_change = True break From d861e556319bcc4f34fba481d6ec1e0aef9fbc84 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 22 Mar 2023 21:49:00 +0800 Subject: [PATCH 30/59] update the frame range settings --- openpype/hosts/max/api/lib.py | 72 ++++++++++++++--------------------- 1 file changed, 28 insertions(+), 44 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index f1d1f91dd1..ac8f6aedfe 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -6,13 +6,10 @@ from pymxs import runtime as rt from typing import Union import contextlib -from openpype.client import ( - get_project, - get_asset_by_name +from openpype.pipeline.context_tools import ( + get_current_project_asset, + get_current_project ) -from openpype.pipeline import legacy_io - -from openpype.pipeline.context_tools import get_current_project_asset JSON_PREFIX = "JSON::" @@ -165,7 +162,7 @@ def get_multipass_setting(project_setting=None): ["multipass"]) -def set_scene_resolution(width, height): +def set_scene_resolution(width: int, height: int): """Set the render resolution Args: @@ -189,49 +186,43 @@ def reset_scene_resolution(): Returns: None """ - project_name = legacy_io.active_project() - project_doc = get_project(project_name) - project_data = project_doc["data"] - asset_data = get_current_project_asset()["data"] - + data = ["data.resolutionWidth", "data.resolutionHeight"] + project_resolution = get_current_project(fields=data)["data"] + project_resolution_data = project_resolution["data"] + asset_resolution = get_current_project_asset(fields=data)["data"] + asset_resolution_data = asset_resolution["data"] # Set project resolution - width_key = "resolutionWidth" - height_key = "resolutionHeight" - proj_width_key = project_data.get(width_key, 1920) - proj_height_key = project_data.get(height_key, 1080) - - width = asset_data.get(width_key, proj_width_key) - height = asset_data.get(height_key, proj_height_key) + project_width = int(project_resolution_data.get("resolutionWidth", 1920)) + project_height = int(project_resolution_data.get("resolutionHeight", 1080)) + width = int(asset_resolution_data.get("resolutionWidth", project_width)) + height = int(asset_resolution_data.get("resolutionHeight", project_height)) set_scene_resolution(width, height) -def get_frame_range(): - """Get the current assets frame range and handles.""" - # Set frame start/end - project_name = legacy_io.active_project() - asset_name = legacy_io.Session["AVALON_ASSET"] - asset = get_asset_by_name(project_name, asset_name) +def get_frame_range() -> dict: + """Get the current assets frame range and handles. + Returns: + dict: with frame start, frame end, handle start, handle end. + """ + # Set frame start/end + asset = get_current_project_asset() frame_start = asset["data"].get("frameStart") frame_end = asset["data"].get("frameEnd") # Backwards compatibility if frame_start is None or frame_end is None: frame_start = asset["data"].get("edit_in") frame_end = asset["data"].get("edit_out") - if frame_start is None or frame_end is None: return - handles = asset["data"].get("handles") or 0 handle_start = asset["data"].get("handleStart") if handle_start is None: handle_start = handles - handle_end = asset["data"].get("handleEnd") if handle_end is None: handle_end = handles - return { "frameStart": frame_start, "frameEnd": frame_end, @@ -240,29 +231,24 @@ def get_frame_range(): } -def reset_frame_range(fps=True): - """Set frame range to current asset +def reset_frame_range(fps: bool=True): + """Set frame range to current asset. - Args: + This is part of 3dsmax documentation: animationRange: A System Global variable which lets you get and - set an Interval value that defines the start and end frames - of the Active Time Segment. + set an Interval value that defines the start and end frames + of the Active Time Segment. frameRate: A System Global variable which lets you get - and set an Integer value that defines the current - scene frame rate in frames-per-second. + and set an Integer value that defines the current + scene frame rate in frames-per-second. """ if fps: - fps_number = float(legacy_io.Session.get("AVALON_FPS", - 25)) + fps_number = float(get_current_project(fields=["data.fps"])["data"]["fps"]) rt.frameRate = fps_number - frame_range = get_frame_range() - frame_start = frame_range["frameStart"] - int(frame_range["handleStart"]) frame_end = frame_range["frameEnd"] + int(frame_range["handleEnd"]) - frange_cmd = f"animationRange = interval {frame_start} {frame_end}" - rt.execute(frange_cmd) @@ -281,8 +267,6 @@ def set_context_setting(): """ reset_scene_resolution() - reset_frame_range() - def get_max_version(): """ From 4e8354eec810023d83a23616c1af0d76035932a6 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 22 Mar 2023 21:54:43 +0800 Subject: [PATCH 31/59] hound fix --- openpype/hosts/max/api/lib.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index ac8f6aedfe..09edaaa2ef 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -182,7 +182,6 @@ def reset_scene_resolution(): scene resolution can be overwritten by an asset if the asset.data contains any information regarding scene resolution . - Returns: None """ @@ -204,7 +203,7 @@ def get_frame_range() -> dict: """Get the current assets frame range and handles. Returns: - dict: with frame start, frame end, handle start, handle end. + dict: with frame start, frame end, handle start, handle end. """ # Set frame start/end asset = get_current_project_asset() @@ -233,17 +232,18 @@ def get_frame_range() -> dict: def reset_frame_range(fps: bool=True): """Set frame range to current asset. + This is part of 3dsmax documentation: - This is part of 3dsmax documentation: - animationRange: A System Global variable which lets you get and - set an Interval value that defines the start and end frames - of the Active Time Segment. - frameRate: A System Global variable which lets you get - and set an Integer value that defines the current - scene frame rate in frames-per-second. + animationRange: A System Global variable which lets you get and + set an Interval value that defines the start and end frames + of the Active Time Segment. + frameRate: A System Global variable which lets you get + and set an Integer value that defines the current + scene frame rate in frames-per-second. """ if fps: - fps_number = float(get_current_project(fields=["data.fps"])["data"]["fps"]) + data_fps = get_current_project(fields=["data.fps"]) + fps_number = float(data_fps["data"]["fps"]) rt.frameRate = fps_number frame_range = get_frame_range() frame_start = frame_range["frameStart"] - int(frame_range["handleStart"]) From e373ccf4e3a747d3db3266f56478cdacfeb0aa3c Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 22 Mar 2023 21:57:19 +0800 Subject: [PATCH 32/59] hound fix --- openpype/hosts/max/api/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 09edaaa2ef..c398d7cf48 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -230,7 +230,7 @@ def get_frame_range() -> dict: } -def reset_frame_range(fps: bool=True): +def reset_frame_range(fps:bool=True): """Set frame range to current asset. This is part of 3dsmax documentation: From 57308ff488e0a2f931231a455cad13ca23eaaa7e Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 22 Mar 2023 21:58:29 +0800 Subject: [PATCH 33/59] hound fix --- openpype/hosts/max/api/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index c398d7cf48..aa7f72b26c 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -230,7 +230,7 @@ def get_frame_range() -> dict: } -def reset_frame_range(fps:bool=True): +def reset_frame_range(fps: bool = True): """Set frame range to current asset. This is part of 3dsmax documentation: From 9eadc11941f4cffc6b1061f56f9751efd848c7de Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Wed, 22 Mar 2023 14:58:14 +0000 Subject: [PATCH 34/59] Update openpype/scripts/otio_burnin.py Co-authored-by: Roy Nieterau --- openpype/scripts/otio_burnin.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index bb7a208103..e7c165ba0e 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -684,8 +684,6 @@ if __name__ == "__main__": with open(in_data_json_path, "r") as file_stream: in_data = json.load(file_stream) - print(json.dumps(in_data, indent=4, sort_keys=True)) - burnins_from_data( in_data["input"], in_data["output"], From 22dac59ccf3d6269ec582c15de387fb23bc0e8e9 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 14:58:46 +0000 Subject: [PATCH 35/59] Store burnin data as dictionary directly. --- openpype/hosts/maya/plugins/publish/collect_review.py | 6 ++---- openpype/plugins/publish/extract_burnin.py | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 3d3ee09eed..0857e8224d 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -161,9 +161,7 @@ class CollectReview(pyblish.api.InstancePlugin): ] key = "focalLength" - instance.data[key] = focal_length - try: - instance.data["burninDataMembers"].append(key) + instance.data["burninDataMembers"][key] = focal_length except KeyError: - instance.data["burninDataMembers"] = [key] + instance.data["burninDataMembers"] = {key: focal_length} diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py index de876c8486..8d29f814b5 100644 --- a/openpype/plugins/publish/extract_burnin.py +++ b/openpype/plugins/publish/extract_burnin.py @@ -255,8 +255,7 @@ class ExtractBurnin(publish.Extractor): burnin_data["custom"] = custom_data # Add data members. - for key in instance.data.get("burninDataMembers", []): - burnin_data[key] = instance.data[key] + burnin_data.update(instance.data.get("burninDataMembers", {})) # Add source camera name to burnin data camera_name = repre.get("camera_name") From f0bdc76183098782b1b42b37db8bb9386f3f864a Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 14:59:40 +0000 Subject: [PATCH 36/59] Clean up prints --- openpype/scripts/otio_burnin.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index e7c165ba0e..fa3f1e3389 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -641,10 +641,9 @@ def burnins_from_data( if list_to_convert: text = list_to_convert[0] cmd = convert_list_to_cmd(list_to_convert, 25.0, label=align)# need to fetch fps properly - print("cmd: " + cmd) else: text = value.format(**data) - print(text) + burnin.add_text(text, align, frame_start, frame_end, cmd=cmd) ffmpeg_args = [] From 266992f93ba45706e126358dfc47d9a18aaf015f Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Wed, 22 Mar 2023 15:00:05 +0000 Subject: [PATCH 37/59] Update openpype/scripts/otio_burnin.py Co-authored-by: Roy Nieterau --- openpype/scripts/otio_burnin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index e7c165ba0e..5e32e8d267 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -537,7 +537,7 @@ def burnins_from_data( if not value: continue - if isinstance(value, (dict, tuple)): + if isinstance(value, dict): raise TypeError(( "Expected string or number type." " Got: {} - \"{}\"" From 4f334a1f8061dfb8d38b176f2b8468e33df26c23 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 15:02:31 +0000 Subject: [PATCH 38/59] Update type error message --- openpype/scripts/otio_burnin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index 58727bc6b8..142ab748af 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -539,7 +539,7 @@ def burnins_from_data( if isinstance(value, dict): raise TypeError(( - "Expected string or number type." + "Expected string, number or list type." " Got: {} - \"{}\"" " (Make sure you have new burnin presets)." ).format(str(type(value)), str(value))) From 4f0aafe560be44bd42baff8946ff5d336bf31714 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 15:08:32 +0000 Subject: [PATCH 39/59] Get FPS properly --- openpype/scripts/otio_burnin.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index 142ab748af..ee29d240b2 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -640,7 +640,9 @@ def burnins_from_data( if list_to_convert: text = list_to_convert[0] - cmd = convert_list_to_cmd(list_to_convert, 25.0, label=align)# need to fetch fps properly + cmd = convert_list_to_cmd( + list_to_convert, data["fps"], label=align + ) else: text = value.format(**data) From a364a82b7dddf64bb8178c3e6b93ccc0565328d6 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 15:10:02 +0000 Subject: [PATCH 40/59] Hound --- openpype/scripts/otio_burnin.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index ee29d240b2..4bbb684deb 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -174,7 +174,13 @@ class ModifiedBurnins(ffmpeg_burnins.Burnins): self.options_init.update(options_init) def add_text( - self, text, align, frame_start=None, frame_end=None, options=None, cmd="" + self, + text, + align, + frame_start=None, + frame_end=None, + options=None, + cmd="" ): """ Adding static text to a filter. @@ -450,11 +456,13 @@ def burnins_from_data( True by default. Presets must be set separately. Should be dict with 2 keys: - - "options" - sets look of burnins - colors, opacity,...(more info: ModifiedBurnins doc) + - "options" - sets look of burnins - colors, opacity,... + (more info: ModifiedBurnins doc) - *OPTIONAL* default values are used when not included - "burnins" - contains dictionary with burnins settings - *OPTIONAL* burnins won't be added (easier is not to use this) - - each key of "burnins" represents Alignment, there are 6 possibilities: + - each key of "burnins" represents Alignment, + there are 6 possibilities: TOP_LEFT TOP_CENTERED TOP_RIGHT BOTTOM_LEFT BOTTOM_CENTERED BOTTOM_RIGHT - value must be string with text you want to burn-in From 84817a77a33d4e0236ca7cdc9e7300665f77571c Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 15:42:45 +0000 Subject: [PATCH 41/59] Code cosmetics --- .../hosts/maya/plugins/publish/collect_review.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 0857e8224d..ce11e8a71f 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -5,6 +5,7 @@ import pyblish.api from openpype.client import get_subset_by_name from openpype.pipeline import legacy_io +from openpype.hosts.maya.api.lib import get_attribute_input class CollectReview(pyblish.api.InstancePlugin): @@ -146,19 +147,16 @@ class CollectReview(pyblish.api.InstancePlugin): ) # Collect focal length. - #Refactor to lib or use available lib method. - plug = "{0}.focalLength".format(camera) + attr = camera + ".focalLength" focal_length = None - if not cmds.listConnections(plug, destination=False, source=True): - # Static. - focal_length = cmds.getAttr(plug) - else: - # Dynamic. + if get_attribute_input(attr): start = instance.data["frameStart"] end = instance.data["frameEnd"] + 1 focal_length = [ - cmds.getAttr(plug, time=t) for t in range(int(start), int(end)) + cmds.getAttr(attr, time=t) for t in range(int(start), int(end)) ] + else: + focal_length = cmds.getAttr(attr) key = "focalLength" try: From 7ff781f3bddff9b5923789cb3406e67162c43c1a Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 16:32:41 +0000 Subject: [PATCH 42/59] Clean up temporary files and support float truncating --- openpype/scripts/otio_burnin.py | 89 +++++++++++++++++---------------- 1 file changed, 47 insertions(+), 42 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index 4bbb684deb..afae4f9e08 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -41,9 +41,8 @@ TIMECODE_KEY = "{timecode}" SOURCE_TIMECODE_KEY = "{source_timecode}" -def convert_list_to_cmd(list_to_convert, fps, label=""): +def convert_list_to_commands(list_to_convert, fps, label=""): path = None - #need to clean up temp file when done with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: for i, value in enumerate(list_to_convert): seconds = i / fps @@ -63,10 +62,8 @@ def convert_list_to_cmd(list_to_convert, fps, label=""): f.write(line) f.flush() path = f.name - path = path.replace("\\", "/") - path = path.replace(":", "\\:") - return "sendcmd=f='{}'".format(path) + return path def _get_ffprobe_data(source): @@ -541,6 +538,7 @@ def burnins_from_data( if source_timecode is not None: data[SOURCE_TIMECODE_KEY[1:-1]] = SOURCE_TIMECODE_KEY + clean_up_paths = [] for align_text, value in burnin_values.items(): if not value: continue @@ -583,8 +581,48 @@ def burnins_from_data( print("Source does not have set timecode value.") value = value.replace(SOURCE_TIMECODE_KEY, MISSING_KEY_VALUE) - key_pattern = re.compile(r"(\{.*?[^{0]*\})") + # Convert lists. + cmd = "" + text = None + keys = [i[1] for i in Formatter().parse(value) if i[1] is not None] + list_to_convert = [] + # Warn about nested dictionary support for lists. Ei. we dont support + # it. + if "[" in "".join(keys): + print( + "We dont support converting nested dictionaries to lists," + " so skipping {}".format(value) + ) + else: + for key in keys: + data_value = data[key] + + # Multiple lists are not supported. + if isinstance(data_value, list) and list_to_convert: + raise ValueError( + "Found multiple lists to convert, which is not " + "supported: {}".format(value) + ) + + if isinstance(data_value, list): + print("Found list to convert: {}".format(data_value)) + for v in data_value: + data[key] = v + list_to_convert.append(value.format(**data)) + + if list_to_convert: + value = list_to_convert[0] + path = convert_list_to_commands( + list_to_convert, data["fps"], label=align + ) + cmd = "sendcmd=f='{}'".format(path) + cmd = cmd.replace("\\", "/") + cmd = cmd.replace(":", "\\:") + clean_up_paths.append(path) + + # Failsafe for missing keys. + key_pattern = re.compile(r"(\{.*?[^{0]*\})") missing_keys = [] for group in key_pattern.findall(value): try: @@ -617,42 +655,7 @@ def burnins_from_data( burnin.add_timecode(*args) continue - cmd = "" - text = None - keys = [i[1] for i in Formatter().parse(value) if i[1] is not None] - list_to_convert = [] - - # Warn about nested dictionary support for lists. Ei. we dont support - # it. - if "[" in "".join(keys): - print( - "We dont support converting nested dictionaries to lists," - " so skipping {}".format(value) - ) - else: - for key in keys: - data_value = data[key] - - # Multiple lists are not supported. - if isinstance(data_value, list) and list_to_convert: - raise ValueError( - "Found multiple lists to convert, which is not " - "supported: {}".format(value) - ) - - if isinstance(data_value, list): - print("Found list to convert: {}".format(data_value)) - for v in data_value: - data[key] = v - list_to_convert.append(value.format(**data)) - - if list_to_convert: - text = list_to_convert[0] - cmd = convert_list_to_cmd( - list_to_convert, data["fps"], label=align - ) - else: - text = value.format(**data) + text = value.format(**data) burnin.add_text(text, align, frame_start, frame_end, cmd=cmd) @@ -685,6 +688,8 @@ def burnins_from_data( burnin.render( output_path, args=ffmpeg_args_str, overwrite=overwrite, **data ) + for path in clean_up_paths: + os.remove(path) if __name__ == "__main__": From 833e48ae0f5f31e57b920950a0f5cea38a967263 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 16:43:56 +0000 Subject: [PATCH 43/59] Docs --- website/docs/pype2/admin_presets_plugins.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/docs/pype2/admin_presets_plugins.md b/website/docs/pype2/admin_presets_plugins.md index fcdc09439b..2a30e7e8e9 100644 --- a/website/docs/pype2/admin_presets_plugins.md +++ b/website/docs/pype2/admin_presets_plugins.md @@ -293,6 +293,7 @@ If source representation has suffix **"h264"** and burnin suffix is **"client"** - It is allowed to use [Anatomy templates](admin_config#anatomy) themselves in burnins if they can be filled with available data. - Additional keys in burnins: + | Burnin key | Description | | --- | --- | | frame_start | First frame number. | @@ -303,6 +304,7 @@ If source representation has suffix **"h264"** and burnin suffix is **"client"** | resolution_height | Resolution height. | | fps | Fps of an output. | | timecode | Timecode by frame start and fps. | + | focalLength | **Only available in Maya**

    Camera focal length per frame. Use syntax `{focalLength:.2f}` for decimal truncating. Eg. `35.234985` with `{focalLength:.2f}` would produce `35.23`, whereas `{focalLength:.0f}` would produce `35`. | :::warning `timecode` is specific key that can be **only at the end of content**. (`"BOTTOM_RIGHT": "TC: {timecode}"`) From 62ced23858534c081c4aee84714b236507e64439 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 23 Mar 2023 00:45:58 +0800 Subject: [PATCH 44/59] remove irrelevant attrs of data --- openpype/hosts/max/api/lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index aa7f72b26c..ac7d75db08 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -186,9 +186,9 @@ def reset_scene_resolution(): None """ data = ["data.resolutionWidth", "data.resolutionHeight"] - project_resolution = get_current_project(fields=data)["data"] + project_resolution = get_current_project(fields=data) project_resolution_data = project_resolution["data"] - asset_resolution = get_current_project_asset(fields=data)["data"] + asset_resolution = get_current_project_asset(fields=data) asset_resolution_data = asset_resolution["data"] # Set project resolution project_width = int(project_resolution_data.get("resolutionWidth", 1920)) From 5197aa2ce7737dd15aa6941515a4fc0669edd046 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Mar 2023 11:51:49 +0000 Subject: [PATCH 45/59] Suggestion to change labels. --- .../schemas/projects_schema/schemas/schema_maya_capture.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json index 1f0e4eeffb..cec4b6eb90 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json @@ -19,12 +19,12 @@ { "type": "text", "key": "compression", - "label": "Compression type" + "label": "Encoding" }, { "type": "text", "key": "format", - "label": "Data format" + "label": "Format" }, { "type": "number", From cc7a9f32c1efd58d89f18f0da4101d9df44666c6 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Thu, 23 Mar 2023 14:30:51 +0100 Subject: [PATCH 46/59] :art: add OP startup script for max to cmdline args --- openpype/settings/defaults/system_settings/applications.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/settings/defaults/system_settings/applications.json b/openpype/settings/defaults/system_settings/applications.json index 5fd9b926fb..eb3a88ce66 100644 --- a/openpype/settings/defaults/system_settings/applications.json +++ b/openpype/settings/defaults/system_settings/applications.json @@ -133,7 +133,7 @@ "linux": [] }, "arguments": { - "windows": [], + "windows": ["-U MAXScript {OPENPYPE_ROOT}\\openpype\\hosts\\max\\startup\\startup.ms"], "darwin": [], "linux": [] }, From 0cc5f3ee37e08aa5516d0ca11bebf1c7fea6fd0e Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Fri, 24 Mar 2023 15:44:29 +0100 Subject: [PATCH 47/59] Changed logic as suggested --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 6a1b09dde1..571ed683bb 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -82,8 +82,6 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): if instance.data.get("publish") } - allow_status_change = False - # Check if any family requirement is met for family_requirement in self.status_change_conditions[ "family_requirements" @@ -92,8 +90,8 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): for family in families: match = family_requirement["family"].lower() == family - if match and condition or not condition and not match: - allow_status_change = True + if match and not condition or condition and not match: + allow_status_change = False break if allow_status_change: From aceaef0b213833214472643f580a01121778f143 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 24 Mar 2023 16:24:33 +0100 Subject: [PATCH 48/59] hiero: correct container colors if UpToDate --- openpype/hosts/hiero/api/lib.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/hiero/api/lib.py b/openpype/hosts/hiero/api/lib.py index bbd1edc14a..0d4368529f 100644 --- a/openpype/hosts/hiero/api/lib.py +++ b/openpype/hosts/hiero/api/lib.py @@ -1221,7 +1221,7 @@ def set_track_color(track_item, color): def check_inventory_versions(track_items=None): """ - Actual version color idetifier of Loaded containers + Actual version color identifier of Loaded containers Check all track items and filter only Loader nodes for its version. It will get all versions from database @@ -1249,10 +1249,10 @@ def check_inventory_versions(track_items=None): project_name = legacy_io.active_project() filter_result = filter_containers(containers, project_name) for container in filter_result.latest: - set_track_color(container["_item"], clip_color) + set_track_color(container["_item"], clip_color_last) for container in filter_result.outdated: - set_track_color(container["_item"], clip_color_last) + set_track_color(container["_item"], clip_color) def selection_changed_timeline(event): From 52511c1e3f8924c89a100cdbe2f2d2c34923ef4f Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 27 Mar 2023 10:07:54 +0100 Subject: [PATCH 49/59] Update openpype/scripts/otio_burnin.py Co-authored-by: Roy Nieterau --- openpype/scripts/otio_burnin.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index afae4f9e08..1f151b5dc6 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -42,7 +42,22 @@ SOURCE_TIMECODE_KEY = "{source_timecode}" def convert_list_to_commands(list_to_convert, fps, label=""): - path = None + """Convert a list of values to a drawtext command file for ffmpeg `sendcmd` + + The list of values is expected to have a value per frame. If the video + file ends up being longer than the amount of samples per frame than the + last value will be held. + + Args: + list_to_convert (list): List of values per frame. + fps (float or int): The expected frame per seconds of the output file + label (str): Label for the + + Returns: + str: Filepath to the temporary drawtext command file. + + """ + with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: for i, value in enumerate(list_to_convert): seconds = i / fps @@ -61,9 +76,7 @@ def convert_list_to_commands(list_to_convert, fps, label=""): f.write(line) f.flush() - path = f.name - - return path + return f.name def _get_ffprobe_data(source): From 28a4f09625f6dc7f9aad7c8cd6a26bfe25c4f370 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 27 Mar 2023 10:10:21 +0100 Subject: [PATCH 50/59] Finish method description --- openpype/scripts/otio_burnin.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index 1f151b5dc6..ca0930537c 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -50,8 +50,9 @@ def convert_list_to_commands(list_to_convert, fps, label=""): Args: list_to_convert (list): List of values per frame. - fps (float or int): The expected frame per seconds of the output file - label (str): Label for the + fps (float or int): The expected frame per seconds of the output file. + label (str): Label for the drawtext, if specific drawtext filter is + required Returns: str: Filepath to the temporary drawtext command file. From eaca4f5551032ebea9a0790c331109ce88005290 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 27 Mar 2023 10:10:31 +0100 Subject: [PATCH 51/59] Change method name --- openpype/scripts/otio_burnin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index ca0930537c..57a1dcfaff 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -41,7 +41,7 @@ TIMECODE_KEY = "{timecode}" SOURCE_TIMECODE_KEY = "{source_timecode}" -def convert_list_to_commands(list_to_convert, fps, label=""): +def convert_list_to_command(list_to_convert, fps, label=""): """Convert a list of values to a drawtext command file for ffmpeg `sendcmd` The list of values is expected to have a value per frame. If the video @@ -627,7 +627,7 @@ def burnins_from_data( if list_to_convert: value = list_to_convert[0] - path = convert_list_to_commands( + path = convert_list_to_command( list_to_convert, data["fps"], label=align ) cmd = "sendcmd=f='{}'".format(path) From a178ca1569a43c1becfba3db0209ba3f982d4959 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 27 Mar 2023 17:35:45 +0800 Subject: [PATCH 52/59] remove duplicated imported function --- openpype/hosts/max/api/menu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/menu.py b/openpype/hosts/max/api/menu.py index b52acc3c38..066cc90039 100644 --- a/openpype/hosts/max/api/menu.py +++ b/openpype/hosts/max/api/menu.py @@ -5,7 +5,7 @@ from pymxs import runtime as rt from openpype.tools.utils import host_tools from openpype.hosts.max.api import lib -from openpype.hosts.max.api import lib + class OpenPypeMenu(object): """Object representing OpenPype menu. From 2244a634b25a4191349db3d994c909359bed9c86 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 27 Mar 2023 16:06:52 +0200 Subject: [PATCH 53/59] change minimum frame start/end to '0' (#4719) --- openpype/tools/project_manager/project_manager/view.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/tools/project_manager/project_manager/view.py b/openpype/tools/project_manager/project_manager/view.py index b35491c5b2..2cf11b702d 100644 --- a/openpype/tools/project_manager/project_manager/view.py +++ b/openpype/tools/project_manager/project_manager/view.py @@ -72,8 +72,8 @@ class HierarchyView(QtWidgets.QTreeView): column_delegate_defs = { "name": NameDef(), "type": TypeDef(), - "frameStart": NumberDef(1), - "frameEnd": NumberDef(1), + "frameStart": NumberDef(0), + "frameEnd": NumberDef(0), "fps": NumberDef(1, decimals=3, step=1), "resolutionWidth": NumberDef(0), "resolutionHeight": NumberDef(0), From 0778dd3ec763aa2257f235b310041aed18902b30 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Mon, 27 Mar 2023 15:28:21 +0000 Subject: [PATCH 54/59] [Automated] Release --- CHANGELOG.md | 668 ++++++++++++++++++++++++++++++++++++++++++++ openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 670 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 145c2e2c1a..78ea53f3d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,674 @@ # Changelog +[Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.2...3.15.3) + +### **πŸ†• New features** + + +
    +Data Exchanges: Point Cloud for 3dsMax #4532 + +Publish PRT format with tyFlow in 3dsmax + +Publish PRT format with tyFlow in 3dsmax and possibly set up loader to load the format too. +- [x] creator +- [x] extractor +- [x] validator +- [x] loader + + +___ + +
    + + +
    +MaxScene Family #4615 + +Introduction of the Max Scene Family + + +___ + +
    + + +
    +Blender: Extract Review #3616 + +Added Review to Blender. + +This implementation is based on #3508 but made compatible for the current implementation of OpenPype for Blender. + + +___ + +
    + + +
    +Global: persistent staging directory for renders #4583 + +Allows configure if staging directory (`stagingDir`) should be persistent with use of profiles. + +With this feature, users can specify a transient data folder path based on presets, which can be used during the creation and publishing stages. In some cases, these DCCs automatically add a rendering path during the creation stage, which is then used in publishing.One of the key advantages of this feature is that it allows users to take advantage of faster storages for rendering, which can help improve workflow efficiency. Additionally, this feature allows users to keep their rendered data persistent, and use their own infrastructure for regular cleaning.However, it should be noted that some productions may want to use this feature without persistency. Furthermore, there may be a need for retargeting the rendering folder to faster storages, which is also not supported at the moment.It is studio responsibility to clean up obsolete folders with data.Location of the folder is configured in `project_anatomy/templates/others`. ('transient' key is expected, with 'folder' key, could be more templates)Which family/task type/subset is applicable is configured in:`project_settings/global/tools/publish/transient_dir_profiles` + + +___ + +
    + +### **πŸš€ Enhancements** + + +
    +Maya: Multiple values on single render attribute - OP-4131 #4631 + +When validating render attributes, this adds support for multiple values. When repairing first value in list is used. + + +___ + +
    + + +
    +Maya: enable 2D Pan/Zoom for playblasts - OP-5213 #4687 + +Setting for enabling 2D Pan/Zoom on reviews. + + +___ + +
    + + +
    +Houdini: Create button open new publisher's "create" tab #4601 + +During a talk with @maxpareschi he mentioned that the new publisher in Houdini felt super confusing due to "Create" going to the older creator but now being completely empty and the publish button directly went to the publish tab.This resolves that by fixing the Create button to now open the new publisher but on the Create tab.Also made publish button enforce going to the "publish" tab for consistency in usage.@antirotor I think changing the Create button's callback was just missed in this commit or was there a specific reason to not change that around yet? + + +___ + +
    + + +
    +Resolution settings referenced from DB record for 3dsMax #4652 + +- Add Callback for setting the resolution according to DB after the new scene is created. +- Add a new Action into openpype menu which allows the user to reset the resolution in 3dsMax + + +___ + +
    + + +
    +scene length setting referenced from DB record for 3dsMax #4665 + +Setting the timeline length based on DB record in 3dsMax Hosts + + +___ + +
    + + +
    +increment workfile version 3dsmax #4685 + +increment workfile version in 3dsmax as if in blender and maya hosts. + + +___ + +
    + + +
    +Copy existing or generate new Fusion profile on prelaunch #4572 + +Fusion preferences will be copied to the predefined `~/.openpype/hosts/fusion/prefs` folder (or any other folder set in system settings) on launch. + +The idea is to create a copy of existing Fusion profile, adding an OpenPype menu to the Fusion instance.By default the copy setting is turned off, so no file copying is performed. Instead the clean Fusion profile is created by Fusion in the predefined folder. The default locaion is set to `~/.openpype/hosts/fusion/prefs`, to better comply with the other os platforms. After creating the default profile, some modifications are applied: +- forced Python3 +- forced English interface +- setup Openpype specific path maps.If the `copy_prefs` checkbox is toggled, a copy of existing Fusion profile folder will be placed in the mentioned location. Then they are altered the same way as described above. The operation is run only once, on the first launch, unless the `force_sync [Resync profile on each launch]` is toggled.English interface is forced because the `FUSION16_PROFILE_DIR` environment variable is not read otherwise (seems to be a Fusion bug). + + +___ + +
    + + +
    +Fusion publish existing frames #4611 + +This PR adds the function to publish existing frames instead of having to re-render all of them for each new publish.I have split the render_locally plugin so the review-part is its own plugin now.I also change the saver-creator-plugin's label from Saver to Render (saver) as I intend to add a Prerender creator like in Nuke. + + +___ + +
    + + +
    +Clockify: refresh and fix the integration #4607 + +Due to recent API changes, Clockify requires `user_id` to operate with the timers. I updated this part and currently it is a WIP for making it fully functional. Most functions, such as start and stop timer, and projects sync are currently working. For the rate limiting task new dependency is added: https://pypi.org/project/ratelimiter/ + + +___ + +
    + + +
    +Publisher: Windows reduce command window pop-ups during Publishing #4672 + +Reduce the command line pop-ups that show on Windows during publishing. + + +___ + +
    + + +
    +CelAction: conditional workfile parameters from settings #4677 + +Since some productions were requesting excluding some workfile parameters from publishing submission, we needed to move them to settings so those could be altered per project. + + +___ + +
    + + +
    +Fix name and docstring for Create Workdir Extra Folders prelaunch hook #4683 + +Fix class name and docstring for Create Workdir Extra Folders prelaunch hookThe class name and docstring were originally copied from another plug-in and didn't match the plug-in logic.This also fixes potentially seeing this twice in your logs. Before:After:Where it was actually running both this prelaunch hook and the actual `AddLastWorkfileToLaunchArgs` plugin. + + +___ + +
    + +### **πŸ› Bug fixes** + + +
    +Maya: Fix getting non-active model panel. #2968 + +When capturing multiple cameras with image planes that have file sequences playing, only the active (first) camera will play through the file sequence. + + +___ + +
    + + +
    +Maya: Fix broken review publishing. #4549 + +Resolves #4547 + + +___ + +
    + + +
    +Maya: Avoid error on right click in Loader if `mtoa` is not loaded #4616 + +Fix an error on right clicking in the Loader when `mtoa` is not a loaded plug-in.Additionally if `mtoa` isn't loaded the loader will now load the plug-in before trying to create the arnold standin. + + +___ + +
    + + +
    +Maya: Fix extract look colorspace detection #4618 + +Fix the logic which guesses the colorspace using `arnold` python library. +- Previously it'd error if `mtoa` was not available on path so it still required `mtoa` to be available. +- The guessing colorspace logic doesn't actually require `mtoa` to be loaded, but just the `arnold` python library to be available. This changes the logic so it doesn't require the `mtoa` plugin to get loaded to guess the colorspace. +- The if/else branch was likely not doing what was intended `cmds.loadPlugin("mtoa", quiet=True)` returns None if the plug-in was already loaded. So this would only ever be true if it ends up loading the `mtoa` plugin the first time. +```python +# Tested in Maya 2022.1 +print(cmds.loadPlugin("mtoa", quiet=True)) +# ['mtoa'] +print(cmds.loadPlugin("mtoa", quiet=True)) +# None +``` + + +___ + +
    + + +
    +Maya: Maya Playblast Options overrides - OP-3847 #4634 + +When publishing a review in Maya, the extractor would fail due to wrong (long) panel name. + + +___ + +
    + + +
    +Bugfix/op 2834 fix extract playblast #4701 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + + +
    +Bugfix/op 2834 fix extract playblast #4704 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + + +
    +Maya: bug fix for passing zoom settings if review is attached to subset #4716 + +Fix for attaching review to subset with pan/zoom option. + + +___ + +
    + + +
    +Fixed a bug where a QThread in the splash screen could be destroyed before finishing execution #4647 + +This should fix the occasional behavior of the QThread being destroyed before even its worker returns from the `run()` function.After quiting, it should wait for the QThread object to properly close itself. + + +___ + +
    + + +
    +Max: fix the bug of removing an instance #4617 + +fix the bug of removing an instance in 3dsMax + + +___ + +
    + + +
    +bugfix for 3dsmax publishing error #4637 + +fix the bug of failing publishing job in 3dsMax + + +___ + +
    + + +
    +3dsmax: opening last workfile #4644 + +Supports opening last saved workfile in 3dsmax host. + + +___ + +
    + + +
    +Global | Nuke: fixing farm publishing workflow #4623 + +After Nuke had adopted new publisher with new creators new issues were introduced. Those issues were addressed with this PR. Those are for example broken reviewable video files publishing if published via farm. Also fixed local publishing. + + +___ + +
    + + +
    +Nuke: Nukenodes family instance without frame range #4669 + +No need to add frame range data into `nukenodes` (backdrop) family publishes - since those are timeless. + + +___ + +
    + + +
    +TVPaint: Optional Validation plugins can be de/activated by user #4674 + +Added `OptionalPyblishPluginMixin` to TVpaint plugins that can be optional. + + +___ + +
    + + +
    +Hiero: Creator with correct workfile numeric padding input #4666 + +Creator was showing 99 in workfile input for long time, even if users set default value to 1001 in studio settings. This has been fixed now. + + +___ + +
    + + +
    +Hiero: correct container colors if UpToDate #4708 + +Colors on loaded containers are now correctly identifying real state of version. `Red` for out of date and `green` for up to date. + + +___ + +
    + + +
    +Maya: tile assembly fail in draft - OP-4820 #4416 + +Tile assembly in Deadline was broken. + +Initial bug report revealed other areas of the tile assembly that needed fixing. + + +___ + +
    + + +
    +Scene inventory: Fix code errors when "not found" entries are found #4594 + +Whenever a "NOT FOUND" entry is present a lot of errors happened in the Scene Inventory: +- It started spamming a lot of errors for the VersionDelegate since it had no numeric version (no version at all).Error reported on Discord: +```python +Traceback (most recent call last): + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 65, in paint + text = self.displayText( + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 33, in displayText + assert isinstance(value, numbers.Integral), ( +AssertionError: Version is not integer. "None" +``` +- Right click menu would error on NOT FOUND entries, and thus not show. With this PR it will now _disregard_ not found items for "Set version" and "Remove" but still allow actions.This PR resolves those. + + +___ + +
    + + +
    +Ftrack: Ftrack additional families filtering #4633 + +Ftrack family collector makes sure the subset family is also in instance families for additional families filtering. + + +___ + +
    + + +
    +General: Use right validation for ffmpeg executable #4640 + +Use ffmpeg exec validation for ffmpeg executables instead of oiio exec validation. The validation is used as last possible source of ffmpeg from `PATH` environment variables, which is an edge case but can cause issues. + + +___ + +
    + + +
    +Global: add tags field to thumbnail representation #4660 + +Thumbnail representation might be missing tags field. + + +___ + +
    + + +
    +Kitsu: Slightly less strict with instance data #4678 + +- Allow to take task name from context if asset doesn't have any. Fixes an issue with Photoshop's review instance not having `task` in data. +- Allow to match "review" against both `instance.data["family"]` and `instance.data["families"]` because some instances don't have the primary family in families, e.g. in Photoshop and TVPaint. +- Do not error on Integrate Kitsu Review whenever for whatever reason Integrate Kitsu Note did not created a comment but just log the message that it was unable to connect a review. + + +___ + +
    + + +
    +Refactor _capture #4702 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + +### **πŸ”€ Refactored code** + + +
    +Look Assigner: Move Look Assigner tool since it's Maya only #4604 + +Fix #4357: Move Look Assigner tool to maya since it's Maya only + + +___ + +
    + + +
    +Maya: Remove unused functions from Extract Look #4671 + +Remove unused functions from Maya Extract Look plug-in + + +___ + +
    + + +
    +Extract Review code refactor #3930 + +Trying to reduce complexity of Extract Review plug-in +- Re-use profile filtering from lib +- Remove "combination families" additional filtering which supposedly was from OP v2 +- Simplify 'formatting' for filling gaps +- Use `legacy_io.Session` over `os.environ` + + +___ + +
    + + +
    +Update tests and documentation for `ColormanagedPyblishPluginMixin` #4612 + +Refactor `ExtractorColormanaged` to `ColormanagedPyblishPluginMixin` in tests and documentation. + + +___ + +
    + +### **πŸ“ƒ Documentation** + + +
    +Docs/add architecture document #4344 + +Add `ARCHITECTURE.md` document. + +his document attemps to give a quick overview of the project to help onboarding, it's not an extensive documentation but more of a elevator pitch one-line descriptions of files/directories and what the attempt to do. + + +___ + +
    + + +
    +Docs: Fix some minor grammar/typos #4680 + +Typo/grammar fixes in documentation. + + +___ + +
    + +### **Merged pull requests** + + +
    +Maya: Implement image file node loader #4313 + +Implements a loader for loading texture image into a `file` node in Maya. + +Similar to Maya's hypershade creation of textures on load you have the option to choose for three modes of creating: +- Texture +- Projection +- StencilThese should match what Maya generates if you create those in Maya. +- [x] Load and manage file nodes +- [x] Apply color spaces after #4195 +- [x] Support for _either_ UDIM or image sequence - currently it seems to always load sequences as UDIM automatically. +- [ ] Add support for animation sequences of UDIM textures using the `..exr` path format? + + +___ + +
    + + +
    +Maya Look Assigner: Don't rely on containers for get all assets #4600 + +This resolves #4044 by not actually relying on containers in the scene but instead just rely on finding nodes with `cbId` attributes. As such, imported nodes would also be found and a shader can be assigned (similar to when using get from selection).**Please take into consideration the potential downsides below**Potential downsides would be: +- IF an already loaded look has any dagNodes, say a 3D Projection node - then that will also show up as a loaded asset where previously nodes from loaded looks were ignored. +- If any dag nodes were created locally - they would have gotten `cbId` attributes on scene save and thus the current asset would almost always show? + + +___ + +
    + + +
    +Maya: Unify menu labels for "Set Frame Range" and "Set Resolution" #4605 + +Fix #4109: Unify menu labels for "Set Frame Range" and "Set Resolution"This also tweaks it in Houdini from Reset Frame Range to Set Frame Range. + + +___ + +
    + + +
    +3dsmax: make sure that startup script executes #4695 + +Fixing reliability of OpenPype startup in 3dsmax. + + +___ + +
    + + +
    +Resolve missing OPENPYPE_MONGO in deadline global job preload #4484 + +In the GlobalJobPreLoad plugin, we propose to replace the SpawnProcess by a sub-process and to pass the environment variables in the parameters, since the SpawnProcess under Centos Linux does not pass the environment variables. + +In the GlobalJobPreLoad plugin, the Deadline SpawnProcess is used to start the OpenPype process. The problem is that the SpawnProcess does not pass environment variables, including OPENPYPE_MONGO, to the process when it is under Centos7 linux, and the process gets stuck. We propose to replace it by a subprocess and to pass the variable in the parameters. + + +___ + +
    + + +
    +Maya: Arnold don't reset maya timeline frame range on render creation (or setting render settings) #4603 + +Fix #4429: Do not reset fps or playback timeline on applying or creating render settings + + +___ + +
    + + +
    +Update artist_hosts_maya_arnold.md #4626 + +Correct Arnold docs. +___ + +
    + + +
    +General: Filter available applications #4667 + +Added option to filter applications that don't have valid executable available in settings in launcher and ftrack actions. This option can be disabled in new settings category `Applications`. The filtering is by default disabled. + + +___ + +
    + + + + [Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.1...3.15.2) ### **πŸ†• New features** diff --git a/openpype/version.py b/openpype/version.py index bc5ea7fe7c..b20b133914 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.3-nightly.4" +__version__ = "3.15.3" diff --git a/pyproject.toml b/pyproject.toml index 02370a4f10..42ce5aa32c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.15.2" # OpenPype +version = "3.15.3" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From 85196b68f4273518d62f83473df228487e3082d2 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 27 Mar 2023 17:06:13 +0100 Subject: [PATCH 55/59] Add maya specific burnin profile. --- .../defaults/project_settings/global.json | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/openpype/settings/defaults/project_settings/global.json b/openpype/settings/defaults/project_settings/global.json index aad17d54da..eb74078cf0 100644 --- a/openpype/settings/defaults/project_settings/global.json +++ b/openpype/settings/defaults/project_settings/global.json @@ -249,6 +249,29 @@ } } } + }, + { + "families": [], + "hosts": [ + "maya" + ], + "task_types": [], + "task_names": [], + "subsets": [], + "burnins": { + "maya_burnin": { + "TOP_LEFT": "{yy}-{mm}-{dd}", + "TOP_CENTERED": "{focalLength:.2f} mm", + "TOP_RIGHT": "{anatomy[version]}", + "BOTTOM_LEFT": "{username}", + "BOTTOM_CENTERED": "{asset}", + "BOTTOM_RIGHT": "{frame_start}-{current_frame}-{frame_end}", + "filter": { + "families": [], + "tags": [] + } + } + } } ] }, From c758ec151fa93c8d43e3a0adc95d8cc6326edd7a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 28 Mar 2023 12:57:44 +0200 Subject: [PATCH 56/59] fix action trigger to be only changes_requested --- .github/workflows/project_actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index ca94f3ae77..26bc2b8a1f 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -10,7 +10,7 @@ jobs: pr_review_requested: name: pr_review_requested runs-on: ubuntu-latest - if: github.event_name == 'pull_request' && github.event.action == 'review_requested' + if: github.event_name == 'pull_request_review' && github.event.review.state == 'changes_requested' steps: - name: Move PR to 'Change Requested' uses: leonsteinhaeuser/project-beta-automations@v2.1.0 From 51cf5d2436932988fc1c2218ed1c1aec537b065a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 28 Mar 2023 15:16:57 +0200 Subject: [PATCH 57/59] updating changelog.md --- CHANGELOG.md | 602 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 430 insertions(+), 172 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78ea53f3d0..4e22b783c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,26 @@ # Changelog +## [3.15.3](https://github.com/ynput/OpenPype/tree/3.15.3) + [Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.2...3.15.3) ### **πŸ†• New features** +
    +Blender: Extract Review #3616 + +Added Review to Blender. + +This implementation is based on #3508 but made compatible for the current implementation of OpenPype for Blender. + + +___ + +
    + +
    Data Exchanges: Point Cloud for 3dsMax #4532 @@ -23,30 +38,6 @@ ___
    -
    -MaxScene Family #4615 - -Introduction of the Max Scene Family - - -___ - -
    - - -
    -Blender: Extract Review #3616 - -Added Review to Blender. - -This implementation is based on #3508 but made compatible for the current implementation of OpenPype for Blender. - - -___ - -
    - -
    Global: persistent staging directory for renders #4583 @@ -55,6 +46,28 @@ ___ With this feature, users can specify a transient data folder path based on presets, which can be used during the creation and publishing stages. In some cases, these DCCs automatically add a rendering path during the creation stage, which is then used in publishing.One of the key advantages of this feature is that it allows users to take advantage of faster storages for rendering, which can help improve workflow efficiency. Additionally, this feature allows users to keep their rendered data persistent, and use their own infrastructure for regular cleaning.However, it should be noted that some productions may want to use this feature without persistency. Furthermore, there may be a need for retargeting the rendering folder to faster storages, which is also not supported at the moment.It is studio responsibility to clean up obsolete folders with data.Location of the folder is configured in `project_anatomy/templates/others`. ('transient' key is expected, with 'folder' key, could be more templates)Which family/task type/subset is applicable is configured in:`project_settings/global/tools/publish/transient_dir_profiles` +___ + +
    + + +
    +Kitsu custom comment template #4599 + +Kitsu allows to write markdown in its comment field. This can be something very powerful to deliver dynamic comments with the help the data from the instance.This feature is defaults to off so the admin have to manually set up the comment field the way they want.I have added a basic example on how the comment can look like as the comment-fields default value.To this I want to add some documentation also but that's on its way when the code itself looks good for the reviewers. + + +___ + +
    + + +
    +MaxScene Family #4615 + +Introduction of the Max Scene Family + + ___
    @@ -84,6 +97,22 @@ ___ +
    +Copy existing or generate new Fusion profile on prelaunch #4572 + +Fusion preferences will be copied to the predefined `~/.openpype/hosts/fusion/prefs` folder (or any other folder set in system settings) on launch. + +The idea is to create a copy of existing Fusion profile, adding an OpenPype menu to the Fusion instance.By default the copy setting is turned off, so no file copying is performed. Instead the clean Fusion profile is created by Fusion in the predefined folder. The default locaion is set to `~/.openpype/hosts/fusion/prefs`, to better comply with the other os platforms. After creating the default profile, some modifications are applied: +- forced Python3 +- forced English interface +- setup Openpype specific path maps.If the `copy_prefs` checkbox is toggled, a copy of existing Fusion profile folder will be placed in the mentioned location. Then they are altered the same way as described above. The operation is run only once, on the first launch, unless the `force_sync [Resync profile on each launch]` is toggled.English interface is forced because the `FUSION16_PROFILE_DIR` environment variable is not read otherwise (seems to be a Fusion bug). + + +___ + +
    + +
    Houdini: Create button open new publisher's "create" tab #4601 @@ -95,6 +124,28 @@ ___
    +
    +Clockify: refresh and fix the integration #4607 + +Due to recent API changes, Clockify requires `user_id` to operate with the timers. I updated this part and currently it is a WIP for making it fully functional. Most functions, such as start and stop timer, and projects sync are currently working. For the rate limiting task new dependency is added: https://pypi.org/project/ratelimiter/ + + +___ + +
    + + +
    +Fusion publish existing frames #4611 + +This PR adds the function to publish existing frames instead of having to re-render all of them for each new publish.I have split the render_locally plugin so the review-part is its own plugin now.I also change the saver-creator-plugin's label from Saver to Render (saver) as I intend to add a Prerender creator like in Nuke. + + +___ + +
    + +
    Resolution settings referenced from DB record for 3dsMax #4652 @@ -107,6 +158,17 @@ ___
    +
    +3dsmax: render instance settings in Publish tab #4658 + +Allows user preset the pools, group and use_published settings in Render Creator in the Max Hosts.User can set the settings before or after creating instance in the new publisher + + +___ + +
    + +
    scene length setting referenced from DB record for 3dsMax #4665 @@ -118,55 +180,6 @@ ___
    -
    -increment workfile version 3dsmax #4685 - -increment workfile version in 3dsmax as if in blender and maya hosts. - - -___ - -
    - - -
    -Copy existing or generate new Fusion profile on prelaunch #4572 - -Fusion preferences will be copied to the predefined `~/.openpype/hosts/fusion/prefs` folder (or any other folder set in system settings) on launch. - -The idea is to create a copy of existing Fusion profile, adding an OpenPype menu to the Fusion instance.By default the copy setting is turned off, so no file copying is performed. Instead the clean Fusion profile is created by Fusion in the predefined folder. The default locaion is set to `~/.openpype/hosts/fusion/prefs`, to better comply with the other os platforms. After creating the default profile, some modifications are applied: -- forced Python3 -- forced English interface -- setup Openpype specific path maps.If the `copy_prefs` checkbox is toggled, a copy of existing Fusion profile folder will be placed in the mentioned location. Then they are altered the same way as described above. The operation is run only once, on the first launch, unless the `force_sync [Resync profile on each launch]` is toggled.English interface is forced because the `FUSION16_PROFILE_DIR` environment variable is not read otherwise (seems to be a Fusion bug). - - -___ - -
    - - -
    -Fusion publish existing frames #4611 - -This PR adds the function to publish existing frames instead of having to re-render all of them for each new publish.I have split the render_locally plugin so the review-part is its own plugin now.I also change the saver-creator-plugin's label from Saver to Render (saver) as I intend to add a Prerender creator like in Nuke. - - -___ - -
    - - -
    -Clockify: refresh and fix the integration #4607 - -Due to recent API changes, Clockify requires `user_id` to operate with the timers. I updated this part and currently it is a WIP for making it fully functional. Most functions, such as start and stop timer, and projects sync are currently working. For the rate limiting task new dependency is added: https://pypi.org/project/ratelimiter/ - - -___ - -
    - -
    Publisher: Windows reduce command window pop-ups during Publishing #4672 @@ -178,6 +191,17 @@ ___
    +
    +Publisher: Explicit save #4676 + +Publisher have explicit button to save changes, so reset can happen without saving any changes. Save still happens automatically when publishing is started or on publisher window close. But a popup is shown if context of host has changed. Important context was enhanced by workfile path (if host integration supports it) so workfile changes are captured too. In that case a dialog with confirmation is shown to user. All callbacks that may require save of context were moved to main window to be able handle dialog show at one place. Save changes now returns success so the rest of logic is skipped -> publishing won't start, when save of instances fails.Save and reset buttons have shortcuts (Ctrl + s and Ctrls + r). + + +___ + +
    + +
    CelAction: conditional workfile parameters from settings #4677 @@ -189,12 +213,45 @@ ___
    +
    +Improve logging of used app + tool envs on application launch #4682 + +Improve logging of what apps + tool environments got loaded for an application launch. + + +___ + +
    + +
    Fix name and docstring for Create Workdir Extra Folders prelaunch hook #4683 Fix class name and docstring for Create Workdir Extra Folders prelaunch hookThe class name and docstring were originally copied from another plug-in and didn't match the plug-in logic.This also fixes potentially seeing this twice in your logs. Before:After:Where it was actually running both this prelaunch hook and the actual `AddLastWorkfileToLaunchArgs` plugin. +___ + +
    + + +
    +Application launch context: Include app group name in logger #4684 + +Clarify in logs better what app group the ApplicationLaunchContext belongs to and what application is being launched.Before:After: + + +___ + +
    + + +
    +increment workfile version 3dsmax #4685 + +increment workfile version in 3dsmax as if in blender and maya hosts. + + ___
    @@ -301,9 +358,64 @@ ___
    -Fixed a bug where a QThread in the splash screen could be destroyed before finishing execution #4647 +Maya: tile assembly fail in draft - OP-4820 #4416 -This should fix the occasional behavior of the QThread being destroyed before even its worker returns from the `run()` function.After quiting, it should wait for the QThread object to properly close itself. +Tile assembly in Deadline was broken. + +Initial bug report revealed other areas of the tile assembly that needed fixing. + + +___ + +
    + + +
    +Maya: Yeti Validate Rig Input - OP-3454 #4554 + +Fix Yeti Validate Rig Input + +Existing workflow was broken due to this #3297. + + +___ + +
    + + +
    +Scene inventory: Fix code errors when "not found" entries are found #4594 + +Whenever a "NOT FOUND" entry is present a lot of errors happened in the Scene Inventory: +- It started spamming a lot of errors for the VersionDelegate since it had no numeric version (no version at all).Error reported on Discord: +```python +Traceback (most recent call last): + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 65, in paint + text = self.displayText( + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 33, in displayText + assert isinstance(value, numbers.Integral), ( +AssertionError: Version is not integer. "None" +``` +- Right click menu would error on NOT FOUND entries, and thus not show. With this PR it will now _disregard_ not found items for "Set version" and "Remove" but still allow actions.This PR resolves those. + + +___ + +
    + + +
    +Kitsu: Sync OP with zou, make sure value-data is int or float #4596 + +Currently the data zou pulls is a string and not a value causing some bugs in the pipe where a value is expected (like `Set frame range` in Fusion). + + + +This PR makes sure each value is set with int() or float() so these bugs can't happen later on. + + + +_(A request to cgwire has also bin sent to allow force values only for some metadata columns, but currently the user can enter what ever they want in there)_ ___ @@ -322,6 +434,39 @@ ___
    +
    +Global | Nuke: fixing farm publishing workflow #4623 + +After Nuke had adopted new publisher with new creators new issues were introduced. Those issues were addressed with this PR. Those are for example broken reviewable video files publishing if published via farm. Also fixed local publishing. + + +___ + +
    + + +
    +Ftrack: Ftrack additional families filtering #4633 + +Ftrack family collector makes sure the subset family is also in instance families for additional families filtering. + + +___ + +
    + + +
    +Ftrack: Hierarchical <> Non-Hierarchical attributes sync fix #4635 + +Sync between hierarchical and non-hierarchical attributes should be fixed and work as expected. Action should sync the values as expected and event handler should do it too and only on newly created entities. + + +___ + +
    + +
    bugfix for 3dsmax publishing error #4637 @@ -333,6 +478,17 @@ ___
    +
    +General: Use right validation for ffmpeg executable #4640 + +Use ffmpeg exec validation for ffmpeg executables instead of oiio exec validation. The validation is used as last possible source of ffmpeg from `PATH` environment variables, which is an edge case but can cause issues. + + +___ + +
    + +
    3dsmax: opening last workfile #4644 @@ -345,9 +501,53 @@ ___
    -Global | Nuke: fixing farm publishing workflow #4623 +Fixed a bug where a QThread in the splash screen could be destroyed before finishing execution #4647 -After Nuke had adopted new publisher with new creators new issues were introduced. Those issues were addressed with this PR. Those are for example broken reviewable video files publishing if published via farm. Also fixed local publishing. +This should fix the occasional behavior of the QThread being destroyed before even its worker returns from the `run()` function.After quiting, it should wait for the QThread object to properly close itself. + + +___ + +
    + + +
    +General: Use right plugin class for Collect Comment #4653 + +Collect Comment plugin is instance plugin so should inherit from `InstancePlugin` instead of `ContextPlugin`. + + +___ + +
    + + +
    +Global: add tags field to thumbnail representation #4660 + +Thumbnail representation might be missing tags field. + + +___ + +
    + + +
    +Integrator: Enforce unique destination transfers, disallow overwrites in queued transfers #4662 + +Fix #4656 by enforcing unique destination transfers in the Integrator. It's now disallowed to a destination in the file transaction queue with a new source path during the publish. + + +___ + +
    + + +
    +Hiero: Creator with correct workfile numeric padding input #4666 + +Creator was showing 99 in workfile input for long time, even if users set default value to 1001 in studio settings. This has been fixed now. ___ @@ -377,95 +577,6 @@ ___
    -
    -Hiero: Creator with correct workfile numeric padding input #4666 - -Creator was showing 99 in workfile input for long time, even if users set default value to 1001 in studio settings. This has been fixed now. - - -___ - -
    - - -
    -Hiero: correct container colors if UpToDate #4708 - -Colors on loaded containers are now correctly identifying real state of version. `Red` for out of date and `green` for up to date. - - -___ - -
    - - -
    -Maya: tile assembly fail in draft - OP-4820 #4416 - -Tile assembly in Deadline was broken. - -Initial bug report revealed other areas of the tile assembly that needed fixing. - - -___ - -
    - - -
    -Scene inventory: Fix code errors when "not found" entries are found #4594 - -Whenever a "NOT FOUND" entry is present a lot of errors happened in the Scene Inventory: -- It started spamming a lot of errors for the VersionDelegate since it had no numeric version (no version at all).Error reported on Discord: -```python -Traceback (most recent call last): - File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 65, in paint - text = self.displayText( - File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 33, in displayText - assert isinstance(value, numbers.Integral), ( -AssertionError: Version is not integer. "None" -``` -- Right click menu would error on NOT FOUND entries, and thus not show. With this PR it will now _disregard_ not found items for "Set version" and "Remove" but still allow actions.This PR resolves those. - - -___ - -
    - - -
    -Ftrack: Ftrack additional families filtering #4633 - -Ftrack family collector makes sure the subset family is also in instance families for additional families filtering. - - -___ - -
    - - -
    -General: Use right validation for ffmpeg executable #4640 - -Use ffmpeg exec validation for ffmpeg executables instead of oiio exec validation. The validation is used as last possible source of ffmpeg from `PATH` environment variables, which is an edge case but can cause issues. - - -___ - -
    - - -
    -Global: add tags field to thumbnail representation #4660 - -Thumbnail representation might be missing tags field. - - -___ - -
    - -
    Kitsu: Slightly less strict with instance data #4678 @@ -479,12 +590,34 @@ ___
    +
    +Publisher: Fix reset shortcut sequence #4694 + +Fix bug created in https://github.com/ynput/OpenPype/pull/4676 where key sequence is checked using unsupported method. The check was changed to convert event into `QKeySequence` object which can be compared to prepared sequence. + + +___ + +
    + +
    Refactor _capture #4702 Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. +___ + +
    + + +
    +Hiero: correct container colors if UpToDate #4708 + +Colors on loaded containers are now correctly identifying real state of version. `Red` for out of date and `green` for up to date. + + ___
    @@ -529,12 +662,34 @@ ___
    +
    +Maya: Replace last usages of Qt module #4610 + +Replace last usage of `Qt` module with `qtpy`. This change is needed for `PySide6` support. All changes happened in Maya loader plugins. + + +___ + +
    + +
    Update tests and documentation for `ColormanagedPyblishPluginMixin` #4612 Refactor `ExtractorColormanaged` to `ColormanagedPyblishPluginMixin` in tests and documentation. +___ + +
    + + +
    +Improve logging of used app + tool envs on application launch (minor tweak) #4686 + +Use `app.full_name` for change done in #4682 + + ___
    @@ -555,6 +710,17 @@ ___ +
    +Documentation: Tweak grammar and fix some typos #4613 + +This resolves some grammar and typos in the documentation.Also fixes the extension of some images in after effects docs which used uppercase extension even though files were lowercase extension. + + +___ + +
    + +
    Docs: Fix some minor grammar/typos #4680 @@ -613,9 +779,11 @@ ___
    -3dsmax: make sure that startup script executes #4695 +Resolve missing OPENPYPE_MONGO in deadline global job preload #4484 -Fixing reliability of OpenPype startup in 3dsmax. +In the GlobalJobPreLoad plugin, we propose to replace the SpawnProcess by a sub-process and to pass the environment variables in the parameters, since the SpawnProcess under Centos Linux does not pass the environment variables. + +In the GlobalJobPreLoad plugin, the Deadline SpawnProcess is used to start the OpenPype process. The problem is that the SpawnProcess does not pass environment variables, including OPENPYPE_MONGO, to the process when it is under Centos7 linux, and the process gets stuck. We propose to replace it by a subprocess and to pass the variable in the parameters. ___ @@ -624,11 +792,9 @@ ___
    -Resolve missing OPENPYPE_MONGO in deadline global job preload #4484 +Tests: Added setup_only to tests #4591 -In the GlobalJobPreLoad plugin, we propose to replace the SpawnProcess by a sub-process and to pass the environment variables in the parameters, since the SpawnProcess under Centos Linux does not pass the environment variables. - -In the GlobalJobPreLoad plugin, the Deadline SpawnProcess is used to start the OpenPype process. The problem is that the SpawnProcess does not pass environment variables, including OPENPYPE_MONGO, to the process when it is under Centos7 linux, and the process gets stuck. We propose to replace it by a subprocess and to pass the variable in the parameters. +Allows to download test zip, unzip and restore DB in preparation for new test. ___ @@ -647,6 +813,64 @@ ___
    +
    +Bump @sideway/formula from 3.0.0 to 3.0.1 in /website #4609 + +Bumps [@sideway/formula](https://github.com/sideway/formula) from 3.0.0 to 3.0.1. +
    +Commits + +
    +
    +Maintainer changes +

    This version was pushed to npm by marsup, a new releaser for @​sideway/formula since your current version.

    +
    +
    + + +[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@sideway/formula&package-manager=npm_and_yarn&previous-version=3.0.0&new-version=3.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) + +Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. + +[//]: # (dependabot-automerge-start) +[//]: # (dependabot-automerge-end) + +--- + +
    +Dependabot commands and options +
    + +You can trigger Dependabot actions by commenting on this PR: +- `@dependabot rebase` will rebase this PR +- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it +- `@dependabot merge` will merge this PR after your CI passes on it +- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it +- `@dependabot cancel merge` will cancel a previously requested merge and block automerging +- `@dependabot reopen` will reopen this PR if it is closed +- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually +- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) +- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) +- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) +- `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language +- `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language +- `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language +- `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language + +You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ynput/OpenPype/network/alerts). + +
    +___ + +
    + +
    Update artist_hosts_maya_arnold.md #4626 @@ -656,6 +880,17 @@ ___
    +
    +Maya: Add "Include Parent Hierarchy" option in animation creator plugin #4645 + +Add an option in Project Settings > Maya > Creator Plugins > Create Animation to include (or not) parent hierarchy. This is to avoid artists to check manually the option for all create animation. + + +___ + +
    + +
    General: Filter available applications #4667 @@ -667,7 +902,30 @@ ___
    +
    +3dsmax: make sure that startup script executes #4695 +Fixing reliability of OpenPype startup in 3dsmax. + + +___ + +
    + + +
    +Project Manager: Change minimum frame start/end to '0' #4719 + +Project manager can have frame start/end set to `0`. + + +___ + +
    + + + +## [3.15.2](https://github.com/ynput/OpenPype/tree/3.15.2) [Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.1...3.15.2) From ba1e033815f25d9d9f30a110b3a0cdfc81f3ae36 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Wed, 29 Mar 2023 03:26:05 +0000 Subject: [PATCH 58/59] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index b20b133914..4d6ee5590e 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.3" +__version__ = "3.15.4-nightly.1" From 7264ce3aafd51c8fbd81dd1803a9242c161ad75b Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Wed, 29 Mar 2023 09:17:20 +0100 Subject: [PATCH 59/59] Update openpype/lib/execute.py --- openpype/lib/execute.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/lib/execute.py b/openpype/lib/execute.py index 5ba62f177f..eba75389f1 100644 --- a/openpype/lib/execute.py +++ b/openpype/lib/execute.py @@ -199,7 +199,7 @@ def run_openpype_process(*args, **kwargs): # - fill more if you find more env = clean_envs_for_openpype_process(os.environ) - # Add OpenPype version if we are running from build. + # Only keep OpenPype version if we are running from build. if not is_running_from_build(): env.pop("OPENPYPE_VERSION", None)