From c708388c2084fa11d32ae47db46512a0a4649a90 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Tue, 10 Aug 2021 17:54:04 +0200 Subject: [PATCH 1/2] add support and documentation from maya scene patching --- .../plugins/publish/submit_maya_deadline.py | 162 ++++++++++++------ .../defaults/project_settings/deadline.json | 3 +- .../schema_project_deadline.json | 27 ++- website/docs/admin_hosts_maya.md | 20 +++ ...maya-admin_submit_maya_job_to_deadline.png | Bin 0 -> 28550 bytes 5 files changed, 154 insertions(+), 58 deletions(-) create mode 100644 website/docs/assets/maya-admin_submit_maya_job_to_deadline.png diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index a652da77865..b607d472bdb 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -199,7 +199,7 @@ def get_renderer_variables(renderlayer, root): if extension is None: extension = "png" - if extension == "exr (multichannel)" or extension == "exr (deep)": + if extension in ["exr (multichannel)", "exr (deep)"]: extension = "exr" prefix_attr = "vraySettings.fileNamePrefix" @@ -295,57 +295,70 @@ def process(self, instance): instance.data["toBeRenderedOn"] = "deadline" filepath = None + patches = ( + context.data["project_settings"].get( + "deadline", {}).get( + "publish", {}).get( + "MayaSubmitDeadline", {}).get( + "scene_patches", {}) + ) # Handle render/export from published scene or not ------------------ if self.use_published: + patched_files = [] for i in context: - if "workfile" in i.data["families"]: - assert i.data["publish"] is True, ( - "Workfile (scene) must be published along") - template_data = i.data.get("anatomyData") - rep = i.data.get("representations")[0].get("name") - template_data["representation"] = rep - template_data["ext"] = rep - template_data["comment"] = None - anatomy_filled = anatomy.format(template_data) - template_filled = anatomy_filled["publish"]["path"] - filepath = os.path.normpath(template_filled) - self.log.info("Using published scene for render {}".format( - filepath)) - - if not os.path.exists(filepath): - self.log.error("published scene does not exist!") - raise - # now we need to switch scene in expected files - # because token will now point to published - # scene file and that might differ from current one - new_scene = os.path.splitext( - os.path.basename(filepath))[0] - orig_scene = os.path.splitext( - os.path.basename(context.data["currentFile"]))[0] - exp = instance.data.get("expectedFiles") - - if isinstance(exp[0], dict): - # we have aovs and we need to iterate over them - new_exp = {} - for aov, files in exp[0].items(): - replaced_files = [] - for f in files: - replaced_files.append( - f.replace(orig_scene, new_scene) - ) - new_exp[aov] = replaced_files - instance.data["expectedFiles"] = [new_exp] - else: - new_exp = [] - for f in exp: - new_exp.append( + if "workfile" not in i.data["families"]: + continue + assert i.data["publish"] is True, ( + "Workfile (scene) must be published along") + template_data = i.data.get("anatomyData") + rep = i.data.get("representations")[0].get("name") + template_data["representation"] = rep + template_data["ext"] = rep + template_data["comment"] = None + anatomy_filled = anatomy.format(template_data) + template_filled = anatomy_filled["publish"]["path"] + filepath = os.path.normpath(template_filled) + self.log.info("Using published scene for render {}".format( + filepath)) + + if not os.path.exists(filepath): + self.log.error("published scene does not exist!") + raise + # now we need to switch scene in expected files + # because token will now point to published + # scene file and that might differ from current one + new_scene = os.path.splitext( + os.path.basename(filepath))[0] + orig_scene = os.path.splitext( + os.path.basename(context.data["currentFile"]))[0] + exp = instance.data.get("expectedFiles") + + if isinstance(exp[0], dict): + # we have aovs and we need to iterate over them + new_exp = {} + for aov, files in exp[0].items(): + replaced_files = [] + for f in files: + replaced_files.append( f.replace(orig_scene, new_scene) ) - instance.data["expectedFiles"] = [new_exp] - self.log.info("Scene name was switched {} -> {}".format( - orig_scene, new_scene - )) + new_exp[aov] = replaced_files + instance.data["expectedFiles"] = [new_exp] + else: + new_exp = [] + for f in exp: + new_exp.append( + f.replace(orig_scene, new_scene) + ) + instance.data["expectedFiles"] = [new_exp] + self.log.info("Scene name was switched {} -> {}".format( + orig_scene, new_scene + )) + # patch workfile is needed + if filepath not in patched_files: + patched_file = self._patch_workfile(filepath, patches) + patched_files.append(patched_file) all_instances = [] for result in context.data["results"]: @@ -868,10 +881,11 @@ def _get_arnold_export_payload(self, data): payload["JobInfo"].update(job_info_ext) payload["PluginInfo"].update(plugin_info_ext) - envs = [] - for k, v in payload["JobInfo"].items(): - if k.startswith("EnvironmentKeyValue"): - envs.append(v) + envs = [ + v + for k, v in payload["JobInfo"].items() + if k.startswith("EnvironmentKeyValue") + ] # add app name to environment envs.append( @@ -892,11 +906,8 @@ def _get_arnold_export_payload(self, data): envs.append( "OPENPYPE_ASS_EXPORT_STEP={}".format(1)) - i = 0 - for e in envs: + for i, e in enumerate(envs): payload["JobInfo"]["EnvironmentKeyValue{}".format(i)] = e - i += 1 - return payload def _get_vray_render_payload(self, data): @@ -1003,7 +1014,7 @@ def _requests_post(self, *args, **kwargs): """ if 'verify' not in kwargs: - kwargs['verify'] = False if os.getenv("OPENPYPE_DONT_VERIFY_SSL", True) else True # noqa + kwargs['verify'] = not os.getenv("OPENPYPE_DONT_VERIFY_SSL", True) # add 10sec timeout before bailing out kwargs['timeout'] = 10 return requests.post(*args, **kwargs) @@ -1022,7 +1033,7 @@ def _requests_get(self, *args, **kwargs): """ if 'verify' not in kwargs: - kwargs['verify'] = False if os.getenv("OPENPYPE_DONT_VERIFY_SSL", True) else True # noqa + kwargs['verify'] = not os.getenv("OPENPYPE_DONT_VERIFY_SSL", True) # add 10sec timeout before bailing out kwargs['timeout'] = 10 return requests.get(*args, **kwargs) @@ -1069,3 +1080,42 @@ def smart_replace(string, key_values): result = filename_zero.replace("\\", "/") return result + + def _patch_workfile(self, file, patches): + # type: (str, dict) -> Union[str, None] + """Patch Maya scene. + + This will take list of patches (lines to add) and apply them to + *published* Maya scene file (that is used later for rendering). + + Patches are dict with following structure:: + { + "name": "Name of patch", + "regex": "regex of line before patch", + "line": "line to insert" + } + + Args: + file (str): File to patch. + patches (dict): Dictionary defining patches. + + Returns: + str: Patched file path or None + + """ + if os.path.splitext(file)[1].lower() != ".ma" or not patches: + return None + + compiled_regex = [re.compile(p["regex"]) for p in patches] + with open(file, "r+") as pf: + scene_data = pf.readlines() + for ln, line in enumerate(scene_data): + for i, r in enumerate(compiled_regex): + if re.match(r, line): + scene_data.insert(ln + 1, patches[i]["line"]) + pf.seek(0) + pf.writelines(scene_data) + pf.truncate() + self.log.info( + "Applied {} patch to scene.".format(patches[i]["name"])) + return file diff --git a/openpype/settings/defaults/project_settings/deadline.json b/openpype/settings/defaults/project_settings/deadline.json index 0f2da9f5b05..efeafbb1acb 100644 --- a/openpype/settings/defaults/project_settings/deadline.json +++ b/openpype/settings/defaults/project_settings/deadline.json @@ -45,7 +45,8 @@ "group": "none", "limit": [], "jobInfo": {}, - "pluginInfo": {} + "pluginInfo": {}, + "scene_patches": [] }, "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 8e6a4b10e4b..53c6bf48c07 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json @@ -151,7 +151,7 @@ "type": "dict", "collapsible": true, "key": "MayaSubmitDeadline", - "label": "Submit maya job to deadline", + "label": "Submit Maya job to Deadline", "checkbox_key": "enabled", "children": [ { @@ -213,6 +213,31 @@ "type": "raw-json", "key": "pluginInfo", "label": "Additional PluginInfo data" + }, + { + "type": "list", + "key": "scene_patches", + "label": "Scene patches", + "required_keys": ["name", "regex", "line"], + "object_type": { + "type": "dict", + "children": [ + { + "key": "name", + "label": "Patch name", + "type": "text" + }, { + "key": "regex", + "label": "Patch regex", + "type": "text" + }, { + "key": "line", + "label": "Patch line", + "type": "text" + } + ] + + } } ] }, diff --git a/website/docs/admin_hosts_maya.md b/website/docs/admin_hosts_maya.md index 5e0aa153458..47447983b96 100644 --- a/website/docs/admin_hosts_maya.md +++ b/website/docs/admin_hosts_maya.md @@ -87,6 +87,26 @@ When you publish your model with top group named like `foo_GRP` it will fail. Bu All regexes used here are in Python variant. ::: +### Maya > Deadline submitter +This plugin provides connection between Maya and Deadline. It is using [Deadline Webservice](https://docs.thinkboxsoftware.com/products/deadline/10.0/1_User%20Manual/manual/web-service.html) to submit jobs to farm. +![Maya > Deadline Settings](assets/maya-admin_submit_maya_job_to_deadline.png) + +You can set various aspects of scene submission to farm with per-project settings in **Setting UI**. + + - **Optional** will mark sumission plugin optional + - **Active** will enable/disable plugin + - **Tile Assembler Plugin** will set what should be used to assemble tiles on Deadline. Either **Open Image IO** will be used +or Deadlines **Draft Tile Assembler**. + - **Use Published scene** enable to render from published scene instead of scene in work area. Rendering from published files is much safer. + - **Use Asset dependencies** will mark job pending on farm until asset dependencies are fulfilled - for example Deadline will wait for scene file to be synced to cloud, etc. + - **Group name** use specific Deadline group for the job. + - **Limit Groups** use these Deadline Limit groups for the job. + - **Additional `JobInfo` data** JSON of additional Deadline options that will be embedded in `JobInfo` part of the submission data. + - **Additional `PluginInfo` data** JSON of additional Deadline options that will be embedded in `PluginInfo` part of the submission data. + - **Scene patches** - configure mechanism to add additional lines to published Maya Ascii scene files before they are used for rendering. +This is useful to fix some specific renderer glitches and advanced hacking of Maya Scene files. `Patch name` is label for patch for easier orientation. +`Patch regex` is regex used to find line in file, after `Patch line` string is inserted. Note that you need to add line ending. + ## Custom Menu You can add your custom tools menu into Maya by extending definitions in **Maya -> Scripts Menu Definition**. ![Custom menu definition](assets/maya-admin_scriptsmenu.png) diff --git a/website/docs/assets/maya-admin_submit_maya_job_to_deadline.png b/website/docs/assets/maya-admin_submit_maya_job_to_deadline.png new file mode 100644 index 0000000000000000000000000000000000000000..56b720dc5deea7e891ed8747edac7bdd1f2f041e GIT binary patch literal 28550 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 Date: Wed, 11 Aug 2021 12:47:51 +0200 Subject: [PATCH 2/2] =?UTF-8?q?fix=20hound=20=F0=9F=90=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/deadline/plugins/publish/submit_maya_deadline.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index b607d472bdb..6b52e4b387f 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -1082,7 +1082,7 @@ def smart_replace(string, key_values): return result def _patch_workfile(self, file, patches): - # type: (str, dict) -> Union[str, None] + # type: (str, dict) -> [str, None] """Patch Maya scene. This will take list of patches (lines to add) and apply them to @@ -1117,5 +1117,6 @@ def _patch_workfile(self, file, patches): pf.writelines(scene_data) pf.truncate() self.log.info( - "Applied {} patch to scene.".format(patches[i]["name"])) + "Applied {} patch to scene.".format( + patches[i]["name"])) return file