From 085d803558f894261b5cf24c19b95a2f8a4557d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Wed, 26 Oct 2022 18:37:44 +0200 Subject: [PATCH] :construction: wip on maya royalrender submit plugin --- openpype/modules/royalrender/api.py | 20 ++- .../publish/submit_maya_royalrender.py | 150 ++++++++++++++++++ openpype/modules/royalrender/rr_job.py | 8 +- 3 files changed, 163 insertions(+), 15 deletions(-) create mode 100644 openpype/modules/royalrender/plugins/publish/submit_maya_royalrender.py diff --git a/openpype/modules/royalrender/api.py b/openpype/modules/royalrender/api.py index de1dba8724..c47d50b62b 100644 --- a/openpype/modules/royalrender/api.py +++ b/openpype/modules/royalrender/api.py @@ -15,9 +15,8 @@ class Api: RR_SUBMIT_CONSOLE = 1 RR_SUBMIT_API = 2 - def __init__(self, settings, project=None): + def __init__(self, project=None): self.log = Logger.get_logger("RoyalRender") - self._settings = settings self._initialize_rr(project) def _initialize_rr(self, project=None): @@ -91,21 +90,21 @@ class Api: sys.path.append(os.path.join(self._rr_path, rr_module_path)) - def create_submission(self, jobs, submitter_attributes, file_name=None): - # type: (list[RRJob], list[SubmitterParameter], str) -> SubmitFile + @staticmethod + def create_submission(jobs, submitter_attributes): + # type: (list[RRJob], list[SubmitterParameter]) -> SubmitFile """Create jobs submission file. Args: jobs (list): List of :class:`RRJob` submitter_attributes (list): List of submitter attributes :class:`SubmitterParameter` for whole submission batch. - file_name (str), optional): File path to write data to. Returns: str: XML data of job submission files. """ - raise NotImplementedError + return SubmitFile(SubmitterParameters=submitter_attributes, Jobs=jobs) def submit_file(self, file, mode=RR_SUBMIT_CONSOLE): # type: (SubmitFile, int) -> None @@ -119,15 +118,14 @@ class Api: # self._submit_using_api(file) def _submit_using_console(self, file): - # type: (SubmitFile) -> bool + # type: (SubmitFile) -> None rr_console = os.path.join( self._get_rr_bin_path(), - "rrSubmitterconsole" + "rrSubmitterConsole" ) - if sys.platform.lower() == "darwin": - if "/bin/mac64" in rr_console: - rr_console = rr_console.replace("/bin/mac64", "/bin/mac") + if sys.platform.lower() == "darwin" and "/bin/mac64" in rr_console: + rr_console = rr_console.replace("/bin/mac64", "/bin/mac") if sys.platform.lower() == "win32": if "/bin/win64" in rr_console: diff --git a/openpype/modules/royalrender/plugins/publish/submit_maya_royalrender.py b/openpype/modules/royalrender/plugins/publish/submit_maya_royalrender.py new file mode 100644 index 0000000000..c354cc80a0 --- /dev/null +++ b/openpype/modules/royalrender/plugins/publish/submit_maya_royalrender.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +"""Submitting render job to RoyalRender.""" +import os +import sys +import tempfile + +from maya.OpenMaya import MGlobal # noqa +from pyblish.api import InstancePlugin, IntegratorOrder +from openpype.hosts.maya.api.lib import get_attr_in_layer +from openpype.pipeline.farm.tools import get_published_workfile_instance +from openpype.pipeline.publish import KnownPublishError +from openpype.modules.royalrender.api import Api as rr_api +from openpype.modules.royalrender.rr_job import RRJob, SubmitterParameter + + +class MayaSubmitRoyalRender(InstancePlugin): + label = "Submit to RoyalRender" + order = IntegratorOrder + 0.1 + use_published = True + + def __init__(self, *args, **kwargs): + self._instance = None + self._rrRoot = None + self.scene_path = None + self.job = None + self.submission_parameters = None + self.rr_api = None + + def get_job(self): + """Prepare job payload. + + Returns: + RRJob: RoyalRender job payload. + + """ + def get_rr_platform(): + if sys.platform.lower() in ["win32", "win64"]: + return "win" + elif sys.platform.lower() == "darwin": + return "mac" + else: + return "lx" + + expected_files = self._instance.data["expectedFiles"] + first_file = next(self._iter_expected_files(expected_files)) + output_dir = os.path.dirname(first_file) + self._instance.data["outputDir"] = output_dir + workspace = self._instance.context.data["workspaceDir"] + default_render_file = self._instance.context.data.get('project_settings') \ + .get('maya') \ + .get('RenderSettings') \ + .get('default_render_image_folder') + filename = os.path.basename(self.scene_path) + dirname = os.path.join(workspace, default_render_file) + + job = RRJob( + Software="Maya", + Renderer=self._instance.data["renderer"], + SeqStart=int(self._instance.data["frameStartHandle"]), + SeqEnd=int(self._instance.data["frameEndHandle"]), + SeqStep=int(self._instance.data["byFrameStep"]), + SeqFileOffset=0, + Version="{0:.2f}".format(MGlobal.apiVersion() / 10000), + SceneName=os.path.basename(self.scene_path), + IsActive=True, + ImageDir=dirname, + ImageFilename=filename, + ImageExtension="." + os.path.splitext(filename)[1], + ImagePreNumberLetter=".", + ImageSingleOutputFile=False, + SceneOS=get_rr_platform(), + Camera=self._instance.data["cameras"][0], + Layer=self._instance.data["layer"], + SceneDatabaseDir=workspace, + ImageFramePadding=get_attr_in_layer( + "defaultRenderGlobals.extensionPadding", + self._instance.data["layer"]), + ImageWidth=self._instance.data["resolutionWidth"], + ImageHeight=self._instance.data["resolutionHeight"] + ) + return job + + @staticmethod + def get_submission_parameters(): + return [] + + def create_file(self, name, ext, contents=None): + temp = tempfile.NamedTemporaryFile( + dir=self.tempdir, + suffix=ext, + prefix=name + '.', + delete=False, + ) + + if contents: + with open(temp.name, 'w') as f: + f.write(contents) + + return temp.name + + def process(self, instance): + """Plugin entry point.""" + self._instance = instance + context = instance.context + self.rr_api = rr_api(context.data["project"]) + + # get royalrender module + """ + try: + rr_module = context.data.get( + "openPypeModules")["royalrender"] + except AttributeError: + self.log.error("Cannot get OpenPype RoyalRender module.") + raise AssertionError("OpenPype RoyalRender module not found.") + """ + + self._rrRoot = instance.data["rrPath"] or context.data["defaultRRPath"] # noqa + if not self._rrRoot: + raise KnownPublishError( + ("Missing RoyalRender root. " + "You need to configure RoyalRender module.")) + file_path = None + if self.use_published: + file_path = get_published_workfile_instance() + + # fallback if nothing was set + if not file_path: + self.log.warning("Falling back to workfile") + file_path = context.data["currentFile"] + + self.scene_path = file_path + self.job = self.get_job() + self.log.info(self.job) + self.submission_parameters = self.get_submission_parameters() + + self.process_submission() + + def process_submission(self): + submission = rr_api.create_submission( + [self.job], + self.submission_parameters) + + self.log.debug(submission) + xml = tempfile.NamedTemporaryFile(suffix=".xml", delete=False) + with open(xml.name, "w") as f: + f.write(submission.serialize()) + + self.rr_api.submit_file(file=xml) + + diff --git a/openpype/modules/royalrender/rr_job.py b/openpype/modules/royalrender/rr_job.py index c660eceac7..beb8c17187 100644 --- a/openpype/modules/royalrender/rr_job.py +++ b/openpype/modules/royalrender/rr_job.py @@ -35,7 +35,7 @@ class RRJob: # Is the job enabled for submission? # enabled by default - IsActive = attr.ib() # type: str + IsActive = attr.ib() # type: bool # Sequence settings of this job SeqStart = attr.ib() # type: int @@ -60,7 +60,7 @@ class RRJob: # If you render a single file, e.g. Quicktime or Avi, then you have to # set this value. Videos have to be rendered at once on one client. - ImageSingleOutputFile = attr.ib(default="false") # type: str + ImageSingleOutputFile = attr.ib(default=False) # type: bool # Semi-Required (required for some render applications) # ----------------------------------------------------- @@ -169,11 +169,11 @@ class SubmitFile: # Delete submission file after processing DeleteXML = attr.ib(default=1) # type: int - # List of submitter options per job + # List of the submitter options per job. # list item must be of `SubmitterParameter` type SubmitterParameters = attr.ib(factory=list) # type: list - # List of job is submission batch. + # List of the jobs in submission batch. # list item must be of type `RRJob` Jobs = attr.ib(factory=list) # type: list