Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5f9dbb6
clean up the validation plugins
moonyuet Jul 30, 2026
28d56d3
make sure we got the 3dsmax executable directory for 2026/2027 as sys…
moonyuet Jul 30, 2026
b521736
support vray multicamera render submission
moonyuet Jul 30, 2026
371bf1b
bugfix: make sure the multiple render product does not get camera nam…
moonyuet Jul 30, 2026
7a0abf1
bugfix: make sure the multiple render product does not get camera nam…
moonyuet Jul 30, 2026
3bdaf8d
Merge remote-tracking branch 'origin/bugfix/3dsmax_batch_directory_sh…
moonyuet Jul 30, 2026
21f2a51
fix the syntax error
moonyuet Aug 3, 2026
adc72bc
fix the os error during suprocess
moonyuet Aug 3, 2026
e1d16a1
refactor get the batch render output name
moonyuet Aug 3, 2026
5a3d45e
Make sure view is active for changing camera in the render setting.
moonyuet Aug 4, 2026
db92feb
Merge pull request #160 from ynput/enhancement/add_vray_support_for_m…
moonyuet Aug 4, 2026
8d7de90
ruff fix
moonyuet Aug 5, 2026
724a980
strip(".") should be correct
moonyuet Aug 6, 2026
18f2d50
Add support for arnold renders in terms of multi-camera workflow(only…
moonyuet Aug 6, 2026
d2769db
make sure returning correct iterations for Arnold aov drivers.
moonyuet Aug 7, 2026
31614d2
arnold output path should be camera-based
moonyuet Aug 7, 2026
b467e93
arnold: fix the validate settings and filenameSuffix.
moonyuet Aug 7, 2026
52631cd
Merge branch 'develop' into bugfix/3dsmax_batch_directory_should_be_c…
moonyuet Aug 8, 2026
314d619
update the save camera extract script to support arnold
moonyuet Aug 8, 2026
7c6bb38
use outputfile and specific outputfile name for arnold render
moonyuet Aug 8, 2026
11d0656
fix the validator repair action
moonyuet Aug 9, 2026
1e9d7cb
Merge branch 'develop' into bugfix/3dsmax_batch_directory_should_be_c…
moonyuet Sep 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions client/ayon_max/api/lib_renderproducts.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,12 @@ def get_multiple_render_products(
end_frame = int(rt.rendEnd)

# Always add beauty pass
beauty_files = self.get_expected_beauty(start_frame, end_frame, ext)
beauty_files = self.get_expected_beauty(
start_frame,
end_frame,
ext,
camera=camera,
)
render_output_frames[f"{camera}_beauty"] = beauty_files

# Add AOVs
Expand All @@ -121,14 +126,19 @@ def get_multiple_render_products(
start_frame,
end_frame,
aov_name,
renderer_name
renderer_name,
camera=camera,
)
render_output_frames[f"{camera}_{aov_name}"] = aov_expected_files

return render_output_frames

def get_expected_beauty(
self, start_frame: int, end_frame: int, extension: str
self,
start_frame: int,
end_frame: int,
extension: str,
camera: str | None = None
) -> list[str]:
"""Get expected beauty render output file paths for each frame.

Expand All @@ -154,7 +164,8 @@ def get_expected_beauty(
start_frame,
end_frame,
"",
renderer_name
renderer_name,
camera=camera,
)

def get_render_element_outputfilename(
Expand Down Expand Up @@ -268,6 +279,7 @@ def get_expected_files(
end_frame: int,
aov_name: str,
renderer_name: str,
camera: str | None = None,
) -> list[str]:
"""Get expected files

Expand All @@ -289,6 +301,8 @@ def get_expected_files(
name, ext = os.path.splitext(filename)
name = name.lstrip(".")
aov_name = aov_name.strip()
if camera is not None:
name = f"{name}_{camera}"
for frame in range(start_frame, end_frame + 1):
aov_filename = f"{name}.{frame:04d}{ext}"
expected_aov = os.path.join(directory, aov_filename)
Expand Down
9 changes: 0 additions & 9 deletions client/ayon_max/api/validate_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,7 @@ def get_invalid_renderoutput(
f"Filename should contain the workfile name pattern: {workfile_pattern}."
)
invalid.append((msg, beauty_dir))

beauty_fname = os.path.basename(rt.rendOutputFilename)
if multicam and cameras:
for camera in cameras:
if camera not in beauty_fname:
invalid.append((
"Invalid render output filename",
"Render output filename should contain camera name "
f"{camera} when multiCamera is enabled. Found: {beauty_fname}",
))

if not is_general_default_output_regex_matched(beauty_fname):
invalid.append((
Expand Down
9 changes: 6 additions & 3 deletions client/ayon_max/plugins/publish/save_scenes_for_cameras.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from pymxs import runtime as rt
from ayon_core.lib import run_subprocess
from ayon_max.api.lib import get_max_version
from ayon_max.api.lib_rendersettings import RenderSettings
from ayon_max.api.lib_renderproducts import RenderProducts

Expand Down Expand Up @@ -88,8 +89,10 @@ def process(self, instance):
ext=fmt,
farm=instance.data.get("farm"))
scripts.append(script)
maxbatch_exe = os.path.join(
os.path.dirname(sys.executable), "3dsmaxbatch")
max_directory = os.path.dirname(sys.executable)
if get_max_version() >= 2026:
max_directory = os.path.dirname(max_directory)
maxbatch_exe = os.path.join(max_directory, "3dsmaxbatch")
maxbatch_exe = maxbatch_exe.replace("\\", "/")
if platform.system().lower() == "windows":
maxbatch_exe += ".exe"
Expand All @@ -104,7 +107,7 @@ def process(self, instance):
tmp.write(script + "\n")

full_script = "\n".join(scripts)
self.log.debug(f"Failed running script {tmp_script_path}:\n{full_script}")
self.log.debug(f"Prepared script {tmp_script_path}:\n{full_script}")
current_filepath = current_filepath.replace("\\", "/")
tmp_script_path = tmp_script_path.replace("\\", "/")
run_subprocess([maxbatch_exe, tmp_script_path,
Expand Down
9 changes: 0 additions & 9 deletions client/ayon_max/plugins/publish/validate_rendersettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,6 @@ def get_invalid_render_element_directory(
cls.log.error(msg)
invalid.append((msg, directory))

if multi_camera and cameras:
for camera in cameras:
if camera not in directory:
invalid.append((
"Invalid render element output directory",
"Render element output directory should contain camera name "
f"{camera} when multiCamera is enabled. Found: {directory}",
))

return invalid

@classmethod
Expand Down
Loading