Merge pull request #5124 from ynput/enhancement/OP-5751_render-multiple-cameras

multiple render camera supports for 3dsmax
This commit is contained in:
Ondřej Samohel 2024-01-15 11:54:08 +01:00 committed by GitHub
commit 837acf9b2e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 458 additions and 39 deletions

View file

@ -37,6 +37,95 @@ class RenderProducts(object):
) )
} }
def get_multiple_beauty(self, outputs, cameras):
beauty_output_frames = dict()
for output, camera in zip(outputs, cameras):
filename, ext = os.path.splitext(output)
filename = filename.replace(".", "")
ext = ext.replace(".", "")
start_frame = int(rt.rendStart)
end_frame = int(rt.rendEnd) + 1
new_beauty = self.get_expected_beauty(
filename, start_frame, end_frame, ext
)
beauty_output = ({
f"{camera}_beauty": new_beauty
})
beauty_output_frames.update(beauty_output)
return beauty_output_frames
def get_multiple_aovs(self, outputs, cameras):
renderer_class = get_current_renderer()
renderer = str(renderer_class).split(":")[0]
aovs_frames = {}
for output, camera in zip(outputs, cameras):
filename, ext = os.path.splitext(output)
filename = filename.replace(".", "")
ext = ext.replace(".", "")
start_frame = int(rt.rendStart)
end_frame = int(rt.rendEnd) + 1
if renderer in [
"ART_Renderer",
"V_Ray_6_Hotfix_3",
"V_Ray_GPU_6_Hotfix_3",
"Default_Scanline_Renderer",
"Quicksilver_Hardware_Renderer",
]:
render_name = self.get_render_elements_name()
if render_name:
for name in render_name:
aovs_frames.update({
f"{camera}_{name}": self.get_expected_aovs(
filename, name, start_frame,
end_frame, ext)
})
elif renderer == "Redshift_Renderer":
render_name = self.get_render_elements_name()
if render_name:
rs_aov_files = rt.Execute("renderers.current.separateAovFiles") # noqa
# this doesn't work, always returns False
# rs_AovFiles = rt.RedShift_Renderer().separateAovFiles
if ext == "exr" and not rs_aov_files:
for name in render_name:
if name == "RsCryptomatte":
aovs_frames.update({
f"{camera}_{name}": self.get_expected_aovs(
filename, name, start_frame,
end_frame, ext)
})
else:
for name in render_name:
aovs_frames.update({
f"{camera}_{name}": self.get_expected_aovs(
filename, name, start_frame,
end_frame, ext)
})
elif renderer == "Arnold":
render_name = self.get_arnold_product_name()
if render_name:
for name in render_name:
aovs_frames.update({
f"{camera}_{name}": self.get_expected_arnold_product( # noqa
filename, name, start_frame,
end_frame, ext)
})
elif renderer in [
"V_Ray_6_Hotfix_3",
"V_Ray_GPU_6_Hotfix_3"
]:
if ext != "exr":
render_name = self.get_render_elements_name()
if render_name:
for name in render_name:
aovs_frames.update({
f"{camera}_{name}": self.get_expected_aovs(
filename, name, start_frame,
end_frame, ext)
})
return aovs_frames
def get_aovs(self, container): def get_aovs(self, container):
render_dir = os.path.dirname(rt.rendOutputFilename) render_dir = os.path.dirname(rt.rendOutputFilename)
@ -63,7 +152,7 @@ class RenderProducts(object):
if render_name: if render_name:
for name in render_name: for name in render_name:
render_dict.update({ render_dict.update({
name: self.get_expected_render_elements( name: self.get_expected_aovs(
output_file, name, start_frame, output_file, name, start_frame,
end_frame, img_fmt) end_frame, img_fmt)
}) })
@ -77,14 +166,14 @@ class RenderProducts(object):
for name in render_name: for name in render_name:
if name == "RsCryptomatte": if name == "RsCryptomatte":
render_dict.update({ render_dict.update({
name: self.get_expected_render_elements( name: self.get_expected_aovs(
output_file, name, start_frame, output_file, name, start_frame,
end_frame, img_fmt) end_frame, img_fmt)
}) })
else: else:
for name in render_name: for name in render_name:
render_dict.update({ render_dict.update({
name: self.get_expected_render_elements( name: self.get_expected_aovs(
output_file, name, start_frame, output_file, name, start_frame,
end_frame, img_fmt) end_frame, img_fmt)
}) })
@ -95,7 +184,8 @@ class RenderProducts(object):
for name in render_name: for name in render_name:
render_dict.update({ render_dict.update({
name: self.get_expected_arnold_product( name: self.get_expected_arnold_product(
output_file, name, start_frame, end_frame, img_fmt) output_file, name, start_frame,
end_frame, img_fmt)
}) })
elif renderer in [ elif renderer in [
"V_Ray_6_Hotfix_3", "V_Ray_6_Hotfix_3",
@ -106,7 +196,7 @@ class RenderProducts(object):
if render_name: if render_name:
for name in render_name: for name in render_name:
render_dict.update({ render_dict.update({
name: self.get_expected_render_elements( name: self.get_expected_aovs(
output_file, name, start_frame, output_file, name, start_frame,
end_frame, img_fmt) # noqa end_frame, img_fmt) # noqa
}) })
@ -169,8 +259,8 @@ class RenderProducts(object):
return render_name return render_name
def get_expected_render_elements(self, folder, name, def get_expected_aovs(self, folder, name,
start_frame, end_frame, fmt): start_frame, end_frame, fmt):
"""Get all the expected render element output files. """ """Get all the expected render element output files. """
render_elements = [] render_elements = []
for f in range(start_frame, end_frame): for f in range(start_frame, end_frame):

View file

@ -74,13 +74,13 @@ class RenderSettings(object):
output = os.path.join(output_dir, container) output = os.path.join(output_dir, container)
try: try:
aov_separator = self._aov_chars[( aov_separator = self._aov_chars[(
self._project_settings["maya"] self._project_settings["max"]
["RenderSettings"] ["RenderSettings"]
["aov_separator"] ["aov_separator"]
)] )]
except KeyError: except KeyError:
aov_separator = "." aov_separator = "."
output_filename = "{0}..{1}".format(output, img_fmt) output_filename = f"{output}..{img_fmt}"
output_filename = output_filename.replace("{aov_separator}", output_filename = output_filename.replace("{aov_separator}",
aov_separator) aov_separator)
rt.rendOutputFilename = output_filename rt.rendOutputFilename = output_filename
@ -146,13 +146,13 @@ class RenderSettings(object):
for i in range(render_elem_num): for i in range(render_elem_num):
renderlayer_name = render_elem.GetRenderElement(i) renderlayer_name = render_elem.GetRenderElement(i)
target, renderpass = str(renderlayer_name).split(":") target, renderpass = str(renderlayer_name).split(":")
aov_name = "{0}_{1}..{2}".format(dir, renderpass, ext) aov_name = f"{dir}_{renderpass}..{ext}"
render_elem.SetRenderElementFileName(i, aov_name) render_elem.SetRenderElementFileName(i, aov_name)
def get_render_output(self, container, output_dir): def get_render_output(self, container, output_dir):
output = os.path.join(output_dir, container) output = os.path.join(output_dir, container)
img_fmt = self._project_settings["max"]["RenderSettings"]["image_format"] # noqa img_fmt = self._project_settings["max"]["RenderSettings"]["image_format"] # noqa
output_filename = "{0}..{1}".format(output, img_fmt) output_filename = f"{output}..{img_fmt}"
return output_filename return output_filename
def get_render_element(self): def get_render_element(self):
@ -167,3 +167,61 @@ class RenderSettings(object):
orig_render_elem.append(render_element) orig_render_elem.append(render_element)
return orig_render_elem return orig_render_elem
def get_batch_render_elements(self, container,
output_dir, camera):
render_element_list = list()
output = os.path.join(output_dir, container)
render_elem = rt.maxOps.GetCurRenderElementMgr()
render_elem_num = render_elem.NumRenderElements()
if render_elem_num < 0:
return
img_fmt = self._project_settings["max"]["RenderSettings"]["image_format"] # noqa
for i in range(render_elem_num):
renderlayer_name = render_elem.GetRenderElement(i)
target, renderpass = str(renderlayer_name).split(":")
aov_name = f"{output}_{camera}_{renderpass}..{img_fmt}"
render_element_list.append(aov_name)
return render_element_list
def get_batch_render_output(self, camera):
target_layer_no = rt.batchRenderMgr.FindView(camera)
target_layer = rt.batchRenderMgr.GetView(target_layer_no)
return target_layer.outputFilename
def batch_render_elements(self, camera):
target_layer_no = rt.batchRenderMgr.FindView(camera)
target_layer = rt.batchRenderMgr.GetView(target_layer_no)
outputfilename = target_layer.outputFilename
directory = os.path.dirname(outputfilename)
render_elem = rt.maxOps.GetCurRenderElementMgr()
render_elem_num = render_elem.NumRenderElements()
if render_elem_num < 0:
return
ext = self._project_settings["max"]["RenderSettings"]["image_format"] # noqa
for i in range(render_elem_num):
renderlayer_name = render_elem.GetRenderElement(i)
target, renderpass = str(renderlayer_name).split(":")
aov_name = f"{directory}_{camera}_{renderpass}..{ext}"
render_elem.SetRenderElementFileName(i, aov_name)
def batch_render_layer(self, container,
output_dir, cameras):
outputs = list()
output = os.path.join(output_dir, container)
img_fmt = self._project_settings["max"]["RenderSettings"]["image_format"] # noqa
for cam in cameras:
camera = rt.getNodeByName(cam)
layer_no = rt.batchRenderMgr.FindView(cam)
renderlayer = None
if layer_no == 0:
renderlayer = rt.batchRenderMgr.CreateView(camera)
else:
renderlayer = rt.batchRenderMgr.GetView(layer_no)
# use camera name as renderlayer name
renderlayer.name = cam
renderlayer.outputFilename = f"{output}_{cam}..{img_fmt}"
outputs.append(renderlayer.outputFilename)
return outputs

View file

@ -2,6 +2,7 @@
"""Creator plugin for creating camera.""" """Creator plugin for creating camera."""
import os import os
from openpype.hosts.max.api import plugin from openpype.hosts.max.api import plugin
from openpype.lib import BoolDef
from openpype.hosts.max.api.lib_rendersettings import RenderSettings from openpype.hosts.max.api.lib_rendersettings import RenderSettings
@ -17,15 +18,33 @@ class CreateRender(plugin.MaxCreator):
file = rt.maxFileName file = rt.maxFileName
filename, _ = os.path.splitext(file) filename, _ = os.path.splitext(file)
instance_data["AssetName"] = filename instance_data["AssetName"] = filename
instance_data["multiCamera"] = pre_create_data.get("multi_cam")
num_of_renderlayer = rt.batchRenderMgr.numViews
if num_of_renderlayer > 0:
rt.batchRenderMgr.DeleteView(num_of_renderlayer)
instance = super(CreateRender, self).create( instance = super(CreateRender, self).create(
subset_name, subset_name,
instance_data, instance_data,
pre_create_data) pre_create_data)
container_name = instance.data.get("instance_node") container_name = instance.data.get("instance_node")
sel_obj = self.selected_nodes
if sel_obj:
# set viewport camera for rendering(mandatory for deadline)
RenderSettings(self.project_settings).set_render_camera(sel_obj)
# set output paths for rendering(mandatory for deadline) # set output paths for rendering(mandatory for deadline)
RenderSettings().render_output(container_name) RenderSettings().render_output(container_name)
# TODO: create multiple camera options
if self.selected_nodes:
selected_nodes_name = []
for sel in self.selected_nodes:
name = sel.name
selected_nodes_name.append(name)
RenderSettings().batch_render_layer(
container_name, filename,
selected_nodes_name)
def get_pre_create_attr_defs(self):
attrs = super(CreateRender, self).get_pre_create_attr_defs()
return attrs + [
BoolDef("multi_cam",
label="Multiple Cameras Submission",
default=False),
]

View file

@ -4,8 +4,10 @@ import os
import pyblish.api import pyblish.api
from pymxs import runtime as rt from pymxs import runtime as rt
from openpype.pipeline.publish import KnownPublishError
from openpype.hosts.max.api import colorspace from openpype.hosts.max.api import colorspace
from openpype.hosts.max.api.lib import get_max_version, get_current_renderer from openpype.hosts.max.api.lib import get_max_version, get_current_renderer
from openpype.hosts.max.api.lib_rendersettings import RenderSettings
from openpype.hosts.max.api.lib_renderproducts import RenderProducts from openpype.hosts.max.api.lib_renderproducts import RenderProducts
@ -23,7 +25,6 @@ class CollectRender(pyblish.api.InstancePlugin):
file = rt.maxFileName file = rt.maxFileName
current_file = os.path.join(folder, file) current_file = os.path.join(folder, file)
filepath = current_file.replace("\\", "/") filepath = current_file.replace("\\", "/")
context.data['currentFile'] = current_file context.data['currentFile'] = current_file
files_by_aov = RenderProducts().get_beauty(instance.name) files_by_aov = RenderProducts().get_beauty(instance.name)
@ -39,6 +40,28 @@ class CollectRender(pyblish.api.InstancePlugin):
instance.data["cameras"] = [camera.name] if camera else None # noqa instance.data["cameras"] = [camera.name] if camera else None # noqa
if instance.data.get("multiCamera"):
cameras = instance.data.get("members")
if not cameras:
raise KnownPublishError("There should be at least"
" one renderable camera in container")
sel_cam = [
c.name for c in cameras
if rt.classOf(c) in rt.Camera.classes]
container_name = instance.data.get("instance_node")
render_dir = os.path.dirname(rt.rendOutputFilename)
outputs = RenderSettings().batch_render_layer(
container_name, render_dir, sel_cam
)
instance.data["cameras"] = sel_cam
files_by_aov = RenderProducts().get_multiple_beauty(
outputs, sel_cam)
aovs = RenderProducts().get_multiple_aovs(
outputs, sel_cam)
files_by_aov.update(aovs)
if "expectedFiles" not in instance.data: if "expectedFiles" not in instance.data:
instance.data["expectedFiles"] = list() instance.data["expectedFiles"] = list()
instance.data["files"] = list() instance.data["files"] = list()

View file

@ -0,0 +1,100 @@
import pyblish.api
import os
import sys
import tempfile
from pymxs import runtime as rt
from openpype.lib import run_subprocess
from openpype.hosts.max.api.lib_rendersettings import RenderSettings
from openpype.hosts.max.api.lib_renderproducts import RenderProducts
class SaveScenesForCamera(pyblish.api.InstancePlugin):
"""Save scene files for multiple cameras without
editing the original scene before deadline submission
"""
label = "Save Scene files for cameras"
order = pyblish.api.ExtractorOrder - 0.48
hosts = ["max"]
families = ["maxrender"]
def process(self, instance):
current_folder = rt.maxFilePath
current_filename = rt.maxFileName
current_filepath = os.path.join(current_folder, current_filename)
camera_scene_files = []
scripts = []
filename, ext = os.path.splitext(current_filename)
fmt = RenderProducts().image_format()
cameras = instance.data.get("cameras")
if not cameras:
return
new_folder = f"{current_folder}_{filename}"
os.makedirs(new_folder, exist_ok=True)
for camera in cameras:
new_output = RenderSettings().get_batch_render_output(camera) # noqa
new_output = new_output.replace("\\", "/")
new_filename = f"{filename}_{camera}{ext}"
new_filepath = os.path.join(new_folder, new_filename)
new_filepath = new_filepath.replace("\\", "/")
camera_scene_files.append(new_filepath)
RenderSettings().batch_render_elements(camera)
rt.rendOutputFilename = new_output
rt.saveMaxFile(current_filepath)
script = ("""
from pymxs import runtime as rt
import os
filename = "{filename}"
new_filepath = "{new_filepath}"
new_output = "{new_output}"
camera = "{camera}"
rt.rendOutputFilename = new_output
directory = os.path.dirname(rt.rendOutputFilename)
directory = os.path.join(directory, filename)
render_elem = rt.maxOps.GetCurRenderElementMgr()
render_elem_num = render_elem.NumRenderElements()
if render_elem_num > 0:
ext = "{ext}"
for i in range(render_elem_num):
renderlayer_name = render_elem.GetRenderElement(i)
target, renderpass = str(renderlayer_name).split(":")
aov_name = f"{{directory}}_{camera}_{{renderpass}}..{ext}"
render_elem.SetRenderElementFileName(i, aov_name)
rt.saveMaxFile(new_filepath)
""").format(filename=instance.name,
new_filepath=new_filepath,
new_output=new_output,
camera=camera,
ext=fmt)
scripts.append(script)
maxbatch_exe = os.path.join(
os.path.dirname(sys.executable), "3dsmaxbatch")
maxbatch_exe = maxbatch_exe.replace("\\", "/")
if sys.platform == "windows":
maxbatch_exe += ".exe"
maxbatch_exe = os.path.normpath(maxbatch_exe)
with tempfile.TemporaryDirectory() as tmp_dir_name:
tmp_script_path = os.path.join(
tmp_dir_name, "extract_scene_files.py")
self.log.info("Using script file: {}".format(tmp_script_path))
with open(tmp_script_path, "wt") as tmp:
for script in scripts:
tmp.write(script + "\n")
try:
current_filepath = current_filepath.replace("\\", "/")
tmp_script_path = tmp_script_path.replace("\\", "/")
run_subprocess([maxbatch_exe, tmp_script_path,
"-sceneFile", current_filepath])
except RuntimeError:
self.log.debug("Checking the scene files existing")
for camera_scene in camera_scene_files:
if not os.path.exists(camera_scene):
self.log.error("Camera scene files not existed yet!")
raise RuntimeError("MaxBatch.exe doesn't run as expected")
self.log.debug(f"Found Camera scene:{camera_scene}")

View file

@ -15,6 +15,12 @@ from openpype.pipeline import (
from openpype.pipeline.publish.lib import ( from openpype.pipeline.publish.lib import (
replace_with_published_scene_path replace_with_published_scene_path
) )
from openpype.pipeline.publish import KnownPublishError
from openpype.hosts.max.api.lib import (
get_current_renderer,
get_multipass_setting
)
from openpype.hosts.max.api.lib_rendersettings import RenderSettings
from openpype_modules.deadline import abstract_submit_deadline from openpype_modules.deadline import abstract_submit_deadline
from openpype_modules.deadline.abstract_submit_deadline import DeadlineJobInfo from openpype_modules.deadline.abstract_submit_deadline import DeadlineJobInfo
from openpype.lib import is_running_from_build from openpype.lib import is_running_from_build
@ -54,7 +60,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
cls.priority) cls.priority)
cls.chuck_size = settings.get("chunk_size", cls.chunk_size) cls.chuck_size = settings.get("chunk_size", cls.chunk_size)
cls.group = settings.get("group", cls.group) cls.group = settings.get("group", cls.group)
# TODO: multiple camera instance, separate job infos
def get_job_info(self): def get_job_info(self):
job_info = DeadlineJobInfo(Plugin="3dsmax") job_info = DeadlineJobInfo(Plugin="3dsmax")
@ -71,7 +77,6 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
src_filepath = context.data["currentFile"] src_filepath = context.data["currentFile"]
src_filename = os.path.basename(src_filepath) src_filename = os.path.basename(src_filepath)
job_info.Name = "%s - %s" % (src_filename, instance.name) job_info.Name = "%s - %s" % (src_filename, instance.name)
job_info.BatchName = src_filename job_info.BatchName = src_filename
job_info.Plugin = instance.data["plugin"] job_info.Plugin = instance.data["plugin"]
@ -134,11 +139,11 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
# Add list of expected files to job # Add list of expected files to job
# --------------------------------- # ---------------------------------
exp = instance.data.get("expectedFiles") if not instance.data.get("multiCamera"):
exp = instance.data.get("expectedFiles")
for filepath in self._iter_expected_files(exp): for filepath in self._iter_expected_files(exp):
job_info.OutputDirectory += os.path.dirname(filepath) job_info.OutputDirectory += os.path.dirname(filepath)
job_info.OutputFilename += os.path.basename(filepath) job_info.OutputFilename += os.path.basename(filepath)
return job_info return job_info
@ -163,11 +168,11 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
def process_submission(self): def process_submission(self):
instance = self._instance instance = self._instance
filepath = self.scene_path filepath = instance.context.data["currentFile"]
files = instance.data["expectedFiles"] files = instance.data["expectedFiles"]
if not files: if not files:
raise RuntimeError("No Render Elements found!") raise KnownPublishError("No Render Elements found!")
first_file = next(self._iter_expected_files(files)) first_file = next(self._iter_expected_files(files))
output_dir = os.path.dirname(first_file) output_dir = os.path.dirname(first_file)
instance.data["outputDir"] = output_dir instance.data["outputDir"] = output_dir
@ -181,9 +186,17 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
self.log.debug("Submitting 3dsMax render..") self.log.debug("Submitting 3dsMax render..")
project_settings = instance.context.data["project_settings"] project_settings = instance.context.data["project_settings"]
payload = self._use_published_name(payload_data, project_settings) if instance.data.get("multiCamera"):
job_info, plugin_info = payload self.log.debug("Submitting jobs for multiple cameras..")
self.submit(self.assemble_payload(job_info, plugin_info)) payload = self._use_published_name_for_multiples(
payload_data, project_settings)
job_infos, plugin_infos = payload
for job_info, plugin_info in zip(job_infos, plugin_infos):
self.submit(self.assemble_payload(job_info, plugin_info))
else:
payload = self._use_published_name(payload_data, project_settings)
job_info, plugin_info = payload
self.submit(self.assemble_payload(job_info, plugin_info))
def _use_published_name(self, data, project_settings): def _use_published_name(self, data, project_settings):
# Not all hosts can import these modules. # Not all hosts can import these modules.
@ -206,7 +219,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
files = instance.data.get("expectedFiles") files = instance.data.get("expectedFiles")
if not files: if not files:
raise RuntimeError("No render elements found") raise KnownPublishError("No render elements found")
first_file = next(self._iter_expected_files(files)) first_file = next(self._iter_expected_files(files))
old_output_dir = os.path.dirname(first_file) old_output_dir = os.path.dirname(first_file)
output_beauty = RenderSettings().get_render_output(instance.name, output_beauty = RenderSettings().get_render_output(instance.name,
@ -218,6 +231,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
plugin_data["RenderOutput"] = beauty_name plugin_data["RenderOutput"] = beauty_name
# as 3dsmax has version with different languages # as 3dsmax has version with different languages
plugin_data["Language"] = "ENU" plugin_data["Language"] = "ENU"
renderer_class = get_current_renderer() renderer_class = get_current_renderer()
renderer = str(renderer_class).split(":")[0] renderer = str(renderer_class).split(":")[0]
@ -249,6 +263,120 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
return job_info, plugin_info return job_info, plugin_info
def get_job_info_through_camera(self, camera):
"""Get the job parameters for deadline submission when
multi-camera is enabled.
Args:
infos(dict): a dictionary with job info.
"""
instance = self._instance
context = instance.context
job_info = copy.deepcopy(self.job_info)
exp = instance.data.get("expectedFiles")
src_filepath = context.data["currentFile"]
src_filename = os.path.basename(src_filepath)
job_info.Name = "%s - %s - %s" % (
src_filename, instance.name, camera)
for filepath in self._iter_expected_files(exp):
if camera not in filepath:
continue
job_info.OutputDirectory += os.path.dirname(filepath)
job_info.OutputFilename += os.path.basename(filepath)
return job_info
# set the output filepath with the relative camera
def get_plugin_info_through_camera(self, camera):
"""Get the plugin parameters for deadline submission when
multi-camera is enabled.
Args:
infos(dict): a dictionary with plugin info.
"""
instance = self._instance
# set the target camera
plugin_info = copy.deepcopy(self.plugin_info)
plugin_data = {}
# set the output filepath with the relative camera
if instance.data.get("multiCamera"):
scene_filepath = instance.context.data["currentFile"]
scene_filename = os.path.basename(scene_filepath)
scene_directory = os.path.dirname(scene_filepath)
current_filename, ext = os.path.splitext(scene_filename)
camera_scene_name = f"{current_filename}_{camera}{ext}"
camera_scene_filepath = os.path.join(
scene_directory, f"_{current_filename}", camera_scene_name)
plugin_data["SceneFile"] = camera_scene_filepath
files = instance.data.get("expectedFiles")
if not files:
raise KnownPublishError("No render elements found")
first_file = next(self._iter_expected_files(files))
old_output_dir = os.path.dirname(first_file)
rgb_output = RenderSettings().get_batch_render_output(camera) # noqa
rgb_bname = os.path.basename(rgb_output)
dir = os.path.dirname(first_file)
beauty_name = f"{dir}/{rgb_bname}"
beauty_name = beauty_name.replace("\\", "/")
plugin_info["RenderOutput"] = beauty_name
renderer_class = get_current_renderer()
renderer = str(renderer_class).split(":")[0]
if renderer in [
"ART_Renderer",
"Redshift_Renderer",
"V_Ray_6_Hotfix_3",
"V_Ray_GPU_6_Hotfix_3",
"Default_Scanline_Renderer",
"Quicksilver_Hardware_Renderer",
]:
render_elem_list = RenderSettings().get_batch_render_elements(
instance.name, old_output_dir, camera
)
for i, element in enumerate(render_elem_list):
if camera in element:
elem_bname = os.path.basename(element)
new_elem = f"{dir}/{elem_bname}"
new_elem = new_elem.replace("/", "\\")
plugin_info["RenderElementOutputFilename%d" % i] = new_elem # noqa
if camera:
# set the default camera and target camera
# (weird parameters from max)
plugin_data["Camera"] = camera
plugin_data["Camera1"] = camera
plugin_data["Camera0"] = None
plugin_info.update(plugin_data)
return plugin_info
def _use_published_name_for_multiples(self, data, project_settings):
"""Process the parameters submission for deadline when
user enables multi-cameras option.
Args:
job_info_list (list): A list of multiple job infos
plugin_info_list (list): A list of multiple plugin infos
"""
job_info_list = []
plugin_info_list = []
instance = self._instance
cameras = instance.data.get("cameras", [])
plugin_data = {}
multipass = get_multipass_setting(project_settings)
if multipass:
plugin_data["DisableMultipass"] = 0
else:
plugin_data["DisableMultipass"] = 1
for cam in cameras:
job_info = self.get_job_info_through_camera(cam)
plugin_info = self.get_plugin_info_through_camera(cam)
plugin_info.update(plugin_data)
job_info_list.append(job_info)
plugin_info_list.append(plugin_info)
return job_info_list, plugin_info_list
def from_published_scene(self, replace_in_path=True): def from_published_scene(self, replace_in_path=True):
instance = self._instance instance = self._instance
if instance.data["renderer"] == "Redshift_Renderer": if instance.data["renderer"] == "Redshift_Renderer":

View file

@ -582,16 +582,17 @@ def _create_instances_for_aov(instance, skeleton, aov_filter, additional_data,
group_name = subset group_name = subset
# if there are multiple cameras, we need to add camera name # if there are multiple cameras, we need to add camera name
if isinstance(col, (list, tuple)): expected_filepath = col[0] if isinstance(col, (list, tuple)) else col
cam = [c for c in cameras if c in col[0]] cams = [cam for cam in cameras if cam in expected_filepath]
else: if cams:
# in case of single frame for cam in cams:
cam = [c for c in cameras if c in col] if aov:
if cam: if not aov.startswith(cam):
if aov: subset_name = '{}_{}_{}'.format(group_name, cam, aov)
subset_name = '{}_{}_{}'.format(group_name, cam, aov) else:
else: subset_name = "{}_{}".format(group_name, aov)
subset_name = '{}_{}'.format(group_name, cam) else:
subset_name = '{}_{}'.format(group_name, cam)
else: else:
if aov: if aov:
subset_name = '{}_{}'.format(group_name, aov) subset_name = '{}_{}'.format(group_name, aov)