diff --git a/openpype/hosts/blender/api/render_lib.py b/openpype/hosts/blender/api/render_lib.py index d564b5ebcb..b437078ad8 100644 --- a/openpype/hosts/blender/api/render_lib.py +++ b/openpype/hosts/blender/api/render_lib.py @@ -1,4 +1,4 @@ -import os +from pathlib import Path import bpy @@ -59,7 +59,7 @@ def get_render_product(output_path, name, aov_sep): instance (pyblish.api.Instance): The instance to publish. ext (str): The image format to render. """ - filepath = os.path.join(output_path, name) + filepath = output_path / name.lstrip("/") render_product = f"{filepath}{aov_sep}beauty.####" render_product = render_product.replace("\\", "/") @@ -180,7 +180,7 @@ def set_node_tree(output_path, name, aov_sep, ext, multilayer): return [] output.file_slots.clear() - output.base_path = output_path + output.base_path = str(output_path) aov_file_products = [] @@ -191,8 +191,9 @@ def set_node_tree(output_path, name, aov_sep, ext, multilayer): output.file_slots.new(filepath) - aov_file_products.append( - (render_pass.name, os.path.join(output_path, filepath))) + filename = str(output_path / filepath.lstrip("/")) + + aov_file_products.append((render_pass.name, filename)) node_input = output.inputs[-1] @@ -214,12 +215,11 @@ def imprint_render_settings(node, data): def prepare_rendering(asset_group): name = asset_group.name - filepath = bpy.data.filepath + filepath = Path(bpy.data.filepath) assert filepath, "Workfile not saved. Please save the file first." - file_path = os.path.dirname(filepath) - file_name = os.path.basename(filepath) - file_name, _ = os.path.splitext(file_name) + dirpath = filepath.parent + file_name = Path(filepath.name).stem project = get_current_project_name() settings = get_project_settings(project) @@ -232,7 +232,7 @@ def prepare_rendering(asset_group): set_render_format(ext, multilayer) aov_list, custom_passes = set_render_passes(settings) - output_path = os.path.join(file_path, render_folder, file_name) + output_path = Path.joinpath(dirpath, render_folder, file_name) render_product = get_render_product(output_path, name, aov_sep) aov_file_product = set_node_tree( diff --git a/openpype/hosts/blender/plugins/publish/collect_render.py b/openpype/hosts/blender/plugins/publish/collect_render.py index 00faf85aed..da02f99052 100644 --- a/openpype/hosts/blender/plugins/publish/collect_render.py +++ b/openpype/hosts/blender/plugins/publish/collect_render.py @@ -11,12 +11,12 @@ import pyblish.api class CollectBlenderRender(pyblish.api.InstancePlugin): - """Gather all publishable render layers from renderSetup.""" + """Gather all publishable render instances.""" order = pyblish.api.CollectorOrder + 0.01 hosts = ["blender"] families = ["render"] - label = "Collect Render Layers" + label = "Collect Render" sync_workfile_version = False @staticmethod @@ -78,8 +78,6 @@ class CollectBlenderRender(pyblish.api.InstancePlugin): assert render_data, "No render data found." - self.log.debug(f"render_data: {dict(render_data)}") - render_product = render_data.get("render_product") aov_file_product = render_data.get("aov_file_product") ext = render_data.get("image_format") @@ -101,7 +99,7 @@ class CollectBlenderRender(pyblish.api.InstancePlugin): expected_files = expected_beauty | expected_aovs instance.data.update({ - "family": "render.farm", + "families": ["render", "render.farm"], "frameStart": frame_start, "frameEnd": frame_end, "frameStartHandle": frame_handle_start, @@ -120,5 +118,3 @@ class CollectBlenderRender(pyblish.api.InstancePlugin): "colorspaceView": "ACES 1.0 SDR-video", "renderProducts": colorspace.ARenderProduct(), }) - - self.log.debug(f"data: {instance.data}") diff --git a/openpype/hosts/blender/plugins/publish/increment_workfile_version.py b/openpype/hosts/blender/plugins/publish/increment_workfile_version.py index 7e33fd53fa..9f8d20aedc 100644 --- a/openpype/hosts/blender/plugins/publish/increment_workfile_version.py +++ b/openpype/hosts/blender/plugins/publish/increment_workfile_version.py @@ -14,7 +14,7 @@ class IncrementWorkfileVersion( optional = True hosts = ["blender"] families = ["animation", "model", "rig", "action", "layout", "blendScene", - "pointcache", "render"] + "pointcache", "render.farm"] def process(self, context): if not self.is_active(context.data): diff --git a/openpype/hosts/blender/plugins/publish/validate_deadline_publish.py b/openpype/hosts/blender/plugins/publish/validate_deadline_publish.py index d8826adc9c..bb243f08cc 100644 --- a/openpype/hosts/blender/plugins/publish/validate_deadline_publish.py +++ b/openpype/hosts/blender/plugins/publish/validate_deadline_publish.py @@ -19,7 +19,7 @@ class ValidateDeadlinePublish(pyblish.api.InstancePlugin, """ order = ValidateContentsOrder - families = ["render.farm"] + families = ["render"] hosts = ["blender"] label = "Validate Render Output for Deadline" optional = True diff --git a/openpype/modules/deadline/plugins/publish/submit_blender_deadline.py b/openpype/modules/deadline/plugins/publish/submit_blender_deadline.py index 094f2b1821..8f9e9a7425 100644 --- a/openpype/modules/deadline/plugins/publish/submit_blender_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_blender_deadline.py @@ -6,8 +6,14 @@ import getpass import attr from datetime import datetime -from openpype.lib import is_running_from_build +from openpype.lib import ( + is_running_from_build, + BoolDef, + NumberDef, + TextDef, +) from openpype.pipeline import legacy_io +from openpype.pipeline.publish import OpenPypePyblishPluginMixin from openpype.pipeline.farm.tools import iter_expected_files from openpype.tests.lib import is_in_tests @@ -22,10 +28,11 @@ class BlenderPluginInfo(): SaveFile = attr.ib(default=True) -class BlenderSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): +class BlenderSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, + OpenPypePyblishPluginMixin): label = "Submit Render to Deadline" hosts = ["blender"] - families = ["render.farm"] + families = ["render"] use_published = True priority = 50 @@ -33,6 +40,7 @@ class BlenderSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): jobInfo = {} pluginInfo = {} group = None + job_delay = "00:00:00:00" def get_job_info(self): job_info = DeadlineJobInfo(Plugin="Blender") @@ -67,8 +75,7 @@ class BlenderSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): job_info.Pool = instance.data.get("primaryPool") job_info.SecondaryPool = instance.data.get("secondaryPool") - job_info.Comment = context.data.get("comment") - job_info.Priority = instance.data.get("priority", self.priority) + job_info.Comment = instance.data.get("comment") if self.group != "none" and self.group: job_info.Group = self.group @@ -83,8 +90,10 @@ class BlenderSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): machine_list_key = "Blacklist" render_globals[machine_list_key] = machine_list - job_info.Priority = attr_values.get("priority") - job_info.ChunkSize = attr_values.get("chunkSize") + job_info.ChunkSize = attr_values.get("chunkSize", self.chunk_size) + job_info.Priority = attr_values.get("priority", self.priority) + job_info.ScheduledType = "Once" + job_info.JobDelay = attr_values.get("job_delay", self.job_delay) # Add options from RenderGlobals render_globals = instance.data.get("renderGlobals", {}) @@ -180,3 +189,39 @@ class BlenderSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): the metadata and the rendered files are in the same location. """ return super().from_published_scene(False) + + @classmethod + def get_attribute_defs(cls): + defs = super(BlenderSubmitDeadline, 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.chunk_size, + label="Frame Per Task"), + + TextDef("group", + default=cls.group, + label="Group Name"), + + TextDef("job_delay", + default=cls.job_delay, + label="Job Delay", + placeholder="dd:hh:mm:ss", + tooltip="Delay the job by the specified amount of time. " + "Timecode: dd:hh:mm:ss."), + ]) + + return defs diff --git a/openpype/settings/defaults/project_settings/deadline.json b/openpype/settings/defaults/project_settings/deadline.json index a1df8ccba9..a19464a5c1 100644 --- a/openpype/settings/defaults/project_settings/deadline.json +++ b/openpype/settings/defaults/project_settings/deadline.json @@ -107,7 +107,8 @@ "use_published": true, "priority": 50, "chunk_size": 10, - "group": "none" + "group": "none", + "job_delay": "00:00:00:00" }, "ProcessSubmittedCacheJobOnFarm": { "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 e622dc43a2..1aea778e32 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json @@ -581,6 +581,11 @@ "type": "text", "key": "group", "label": "Group Name" + }, + { + "type": "text", + "key": "job_delay", + "label": "Delay job (timecode dd:hh:mm:ss)" } ] }, diff --git a/server_addon/deadline/server/settings/publish_plugins.py b/server_addon/deadline/server/settings/publish_plugins.py index 7915308d2f..0781902fe5 100644 --- a/server_addon/deadline/server/settings/publish_plugins.py +++ b/server_addon/deadline/server/settings/publish_plugins.py @@ -237,6 +237,7 @@ class BlenderSubmitDeadlineModel(BaseSettingsModel): priority: int = Field(title="Priority") chunk_size: int = Field(title="Frame per Task") group: str = Field("", title="Group Name") + job_delay: str = Field("", title="Delay job (timecode dd:hh:mm:ss)") class AOVFilterSubmodel(BaseSettingsModel): @@ -438,7 +439,8 @@ DEFAULT_DEADLINE_PLUGINS_SETTINGS = { "use_published": True, "priority": 50, "chunk_size": 10, - "group": "none" + "group": "none", + "job_delay": "00:00:00:00" }, "ProcessSubmittedCacheJobOnFarm": { "enabled": True,