Skip to content

validate_rendersettings

ValidateArnoldRenderSetting

Bases: ValidateGenericRenderSetting

Validate Arnold render settings before render submission.

This validator extends the generic render setting validation with Arnold-specific checks. It keeps the shared validation inherited from :class:ValidateGenericRenderSetting, such as validating the beauty output path, render element output directories, filename patterns, and image extension consistency, and adds validation for Arnold AOV output configuration required by the publish pipeline.

The plugin performs the following Arnold-specific validation checks:

 1. Arnold AOV Output Path Validation
     Validates that the Arnold AOV output path points to the expected
     workfile-based render directory for the current scene.

 2. Arnold Driver Type Validation
     Ensures that the first Arnold AOV driver matches the expected
     driver type for the configured AYON image format.

 3. Arnold Multipart Configuration
     Validates that Arnold multipart output matches the multipass
     expectation from the AYON project settings.

 4. Arnold Driver Filename Suffix Validation
     Checks that the Arnold AOV driver filename suffix ends with a dot,
     which is required for correct output filename generation.

The repair action updates the Arnold AOV output path, configures the expected multipart state, replaces an invalid driver type when possible, and fixes the filename suffix so common publish issues can be repaired directly from the validator.

Note

The current implementation validates only the first Arnold AOV driver. Multiple drivers are not supported by this validator yet.

Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
class ValidateArnoldRenderSetting(ValidateGenericRenderSetting):
    """Validate Arnold render settings before render submission.

     This validator extends the generic render setting validation with
     Arnold-specific checks. It keeps the shared validation inherited from
     :class:`ValidateGenericRenderSetting`, such as validating the beauty
     output path, render element output directories, filename patterns, and
     image extension consistency, and adds validation for Arnold AOV output
     configuration required by the publish pipeline.

     The plugin performs the following Arnold-specific validation checks:

          1. Arnold AOV Output Path Validation
              Validates that the Arnold AOV output path points to the expected
              workfile-based render directory for the current scene.

          2. Arnold Driver Type Validation
              Ensures that the first Arnold AOV driver matches the expected
              driver type for the configured AYON image format.

          3. Arnold Multipart Configuration
              Validates that Arnold multipart output matches the multipass
              expectation from the AYON project settings.

          4. Arnold Driver Filename Suffix Validation
              Checks that the Arnold AOV driver filename suffix ends with a dot,
              which is required for correct output filename generation.

     The repair action updates the Arnold AOV output path, configures the
     expected multipart state, replaces an invalid driver type when possible,
     and fixes the filename suffix so common publish issues can be repaired
     directly from the validator.

     Note:
          The current implementation validates only the first Arnold AOV driver.
          Multiple drivers are not supported by this validator yet.
    """

    label = "Validate Arnold Render Setting"

    @classmethod
    def _matches_renderer_name(cls, renderer_name: str) -> bool:
        """Check if the renderer name matches the supported renderers.

        Args:
            renderer_name (str): The name of the renderer to check.

        Returns:
            bool: True if the renderer is supported, False otherwise.
        """
        return renderer_name == "Arnold"

    @classmethod
    def get_invalid_render_settings(
        cls,
        instance: pyblish.api.Instance,
        renderer_name: str,
        workfile_pattern: str,
        renderer: rt.Renderers.current,
        project_settings: dict,
    ) -> list[tuple[str, str]]:
        """Get invalid Arnold settings for the given instance.

        Args:
            instance (pyblish.api.Instance): The instance to validate.
            renderer (rt.Renderers.current): The current renderer.
            renderer_name (str): The name of the renderer.
            workfile_pattern (str): The workfile name pattern.
            project_settings (dict): The project settings dictionary.

        Returns:
            list[tuple[str, str]]: A list of tuples containing error messages
                and invalid values.
        """
        invalid = []
        aov_manager = renderer.AOVManager
        output_path = aov_manager.outputPath
        image_format = instance.data["imageFormat"]
        invalid.extend(
            cls.get_invalid_renderoutput(
            image_format,
            workfile_pattern
        ))
        if workfile_pattern not in output_path:
            msg = (
                f"Invalid Arnold AOV output path {output_path}. "
                f"Output path should contain the workfile name pattern: {workfile_pattern}."
            )
            cls.log.error(msg)
            invalid.append((msg, output_path))

        aov_drivers = aov_manager.drivers
        driver = aov_drivers[0]
        arnold_driver = get_arnold_driver_for_image_format(image_format)
        if rt.ClassOf(driver) != arnold_driver:
            msg = (
                f"Invalid Arnold driver for image format {image_format}.\n"
                f"Should be: {arnold_driver}"
            )
            cls.log.error(msg)
            invalid.append((msg, driver))

        multipass_enabled = get_multipass_setting(renderer_name, project_settings)
        if driver.multipart != multipass_enabled:
            invalid.append((
                "Invalid Arnold multipass setting",
                f"Expected: {multipass_enabled}, Found: {driver.multipart}",
            ))
        if not driver.filenameSuffix.endswith("."):
            invalid.append((
                "Invalid Arnold AOV driver filename",
                "Arnold AOV driver filename suffix should end with '.', "
                f"Found: {driver.filenameSuffix}.",
            ))
        return invalid

    @classmethod
    def repair(cls, instance: pyblish.api.Instance) -> None:
        """Repair invalid Arnold render settings for the given instance.

        Args:
            instance (pyblish.api.Instance): Instance to repair.
        """
        renderer, renderer_name = cls._get_renderer_data(instance)
        if not cls._matches_renderer_name(renderer_name):
            return

        cls.repair_arnold_settings(instance, renderer, renderer_name)

    @classmethod
    def repair_arnold_settings(
        cls,
        instance: pyblish.api.Instance,
        renderer: rt.Renderers.current,
        renderer_name: str,
    ) -> None:
        """Repair invalid Arnold settings for the given instance.

        Args:
            instance (pyblish.api.Instance): The instance to repair.
            renderer (rt.Renderers.current): The current renderer.
            renderer_name (str): The name of the renderer.
        """
        image_format = instance.data["imageFormat"]
        project_settings = instance.context.data["project_settings"]
        aov_manager = renderer.AOVManager
        path = set_correct_workfile_name_for_render_output(
            instance,
            aov_manager.outputPath,
        )
        aov_manager.outputPath = path
        # check if the beauty output path is correct if using the
        # default native 3dsmax render
        render_output = rt.rendOutputFilename
        render_dir = set_correct_workfile_name_for_render_output(
            instance,
            os.path.dirname(render_output),
        )
        filename = os.path.basename(render_output)
        rt.rendOutputFilename = build_general_output_filename(
            render_dir,
            filename,
        )
        driver = aov_manager.drivers[0]
        driver.multipart = get_multipass_setting(
            renderer_name,
            project_settings,
        )
        arnold_driver = get_arnold_driver_for_image_format(image_format)
        if rt.ClassOf(driver) != arnold_driver:
            driver_type = arnold_driver
            if driver_type:
                new_driver = driver_type()
                aov_manager.drivers[0] = new_driver
                driver = new_driver
                driver.filenameSuffix = f"{instance.name}."
                cls.log.info(
                    "Arnold AOV driver has been repaired to %s for image format %s.",
                    new_driver,
                    image_format,
                )
            else:
                cls.log.warning(
                    "No compatible Arnold driver found for image format %s. "
                    "Please set the correct driver manually in render settings.",
                    image_format,
                )

        if not driver.filenameSuffix.endswith("."):
            driver.filenameSuffix = f"{driver.filenameSuffix}."
            cls.log.info(
                "Arnold AOV driver filename suffix has been repaired to %s.",
                driver.filenameSuffix,
            )

get_invalid_render_settings(instance, renderer_name, workfile_pattern, renderer, project_settings) classmethod

Get invalid Arnold settings for the given instance.

Parameters:

Name Type Description Default
instance Instance

The instance to validate.

required
renderer current

The current renderer.

required
renderer_name str

The name of the renderer.

required
workfile_pattern str

The workfile name pattern.

required
project_settings dict

The project settings dictionary.

required

Returns:

Type Description
list[tuple[str, str]]

list[tuple[str, str]]: A list of tuples containing error messages and invalid values.

Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
@classmethod
def get_invalid_render_settings(
    cls,
    instance: pyblish.api.Instance,
    renderer_name: str,
    workfile_pattern: str,
    renderer: rt.Renderers.current,
    project_settings: dict,
) -> list[tuple[str, str]]:
    """Get invalid Arnold settings for the given instance.

    Args:
        instance (pyblish.api.Instance): The instance to validate.
        renderer (rt.Renderers.current): The current renderer.
        renderer_name (str): The name of the renderer.
        workfile_pattern (str): The workfile name pattern.
        project_settings (dict): The project settings dictionary.

    Returns:
        list[tuple[str, str]]: A list of tuples containing error messages
            and invalid values.
    """
    invalid = []
    aov_manager = renderer.AOVManager
    output_path = aov_manager.outputPath
    image_format = instance.data["imageFormat"]
    invalid.extend(
        cls.get_invalid_renderoutput(
        image_format,
        workfile_pattern
    ))
    if workfile_pattern not in output_path:
        msg = (
            f"Invalid Arnold AOV output path {output_path}. "
            f"Output path should contain the workfile name pattern: {workfile_pattern}."
        )
        cls.log.error(msg)
        invalid.append((msg, output_path))

    aov_drivers = aov_manager.drivers
    driver = aov_drivers[0]
    arnold_driver = get_arnold_driver_for_image_format(image_format)
    if rt.ClassOf(driver) != arnold_driver:
        msg = (
            f"Invalid Arnold driver for image format {image_format}.\n"
            f"Should be: {arnold_driver}"
        )
        cls.log.error(msg)
        invalid.append((msg, driver))

    multipass_enabled = get_multipass_setting(renderer_name, project_settings)
    if driver.multipart != multipass_enabled:
        invalid.append((
            "Invalid Arnold multipass setting",
            f"Expected: {multipass_enabled}, Found: {driver.multipart}",
        ))
    if not driver.filenameSuffix.endswith("."):
        invalid.append((
            "Invalid Arnold AOV driver filename",
            "Arnold AOV driver filename suffix should end with '.', "
            f"Found: {driver.filenameSuffix}.",
        ))
    return invalid

repair(instance) classmethod

Repair invalid Arnold render settings for the given instance.

Parameters:

Name Type Description Default
instance Instance

Instance to repair.

required
Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
436
437
438
439
440
441
442
443
444
445
446
447
@classmethod
def repair(cls, instance: pyblish.api.Instance) -> None:
    """Repair invalid Arnold render settings for the given instance.

    Args:
        instance (pyblish.api.Instance): Instance to repair.
    """
    renderer, renderer_name = cls._get_renderer_data(instance)
    if not cls._matches_renderer_name(renderer_name):
        return

    cls.repair_arnold_settings(instance, renderer, renderer_name)

repair_arnold_settings(instance, renderer, renderer_name) classmethod

Repair invalid Arnold settings for the given instance.

Parameters:

Name Type Description Default
instance Instance

The instance to repair.

required
renderer current

The current renderer.

required
renderer_name str

The name of the renderer.

required
Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
@classmethod
def repair_arnold_settings(
    cls,
    instance: pyblish.api.Instance,
    renderer: rt.Renderers.current,
    renderer_name: str,
) -> None:
    """Repair invalid Arnold settings for the given instance.

    Args:
        instance (pyblish.api.Instance): The instance to repair.
        renderer (rt.Renderers.current): The current renderer.
        renderer_name (str): The name of the renderer.
    """
    image_format = instance.data["imageFormat"]
    project_settings = instance.context.data["project_settings"]
    aov_manager = renderer.AOVManager
    path = set_correct_workfile_name_for_render_output(
        instance,
        aov_manager.outputPath,
    )
    aov_manager.outputPath = path
    # check if the beauty output path is correct if using the
    # default native 3dsmax render
    render_output = rt.rendOutputFilename
    render_dir = set_correct_workfile_name_for_render_output(
        instance,
        os.path.dirname(render_output),
    )
    filename = os.path.basename(render_output)
    rt.rendOutputFilename = build_general_output_filename(
        render_dir,
        filename,
    )
    driver = aov_manager.drivers[0]
    driver.multipart = get_multipass_setting(
        renderer_name,
        project_settings,
    )
    arnold_driver = get_arnold_driver_for_image_format(image_format)
    if rt.ClassOf(driver) != arnold_driver:
        driver_type = arnold_driver
        if driver_type:
            new_driver = driver_type()
            aov_manager.drivers[0] = new_driver
            driver = new_driver
            driver.filenameSuffix = f"{instance.name}."
            cls.log.info(
                "Arnold AOV driver has been repaired to %s for image format %s.",
                new_driver,
                image_format,
            )
        else:
            cls.log.warning(
                "No compatible Arnold driver found for image format %s. "
                "Please set the correct driver manually in render settings.",
                image_format,
            )

    if not driver.filenameSuffix.endswith("."):
        driver.filenameSuffix = f"{driver.filenameSuffix}."
        cls.log.info(
            "Arnold AOV driver filename suffix has been repaired to %s.",
            driver.filenameSuffix,
        )

ValidateGenericRenderSetting

Bases: InstancePlugin, ValidateRenderSettingsBase

Validate generic render settings before render submission.

This validator ensures that render output filepaths and filenames are correctly configured for the current 3ds Max scene before submission to the render farm or local render. It validates the rendering settings across multiple supported renderers (V-Ray, Arnold, Redshift, and generic renderers) and provides automated repair capabilities.

The plugin performs the following validation checks:

1. Render Output Directory Structure
   Validates that the render output folder path matches the expected
   project hierarchy based on the current Max scene filename.
   e.g:
     Current Max scene: John_Doe.max
     Expected output directory:
       {root[work]}/{project[name]}/{hierarchy}/{asset}/
       work/{task[name]}/render/3dsmax/John_Doe/

2. Image File Extension Compliance
   Ensures that all render output files use the correct image format
   extension as defined in the AYON project settings.
   e.g:
     Configured format in AYON: png
     Expected render outputs: John_Doe.png (and all render elements)
     Invalid outputs: John_Doe.jpg or John_Doe.exr (if format is png)

3. Render Element Filename Validation
   Checks that each render element output filename follows the naming
   convention and ends with the render element's identifier from the
   3ds Max Render Element Manager.
   e.g.
     Render element name: RsCryptomatte
     Expected filename format: {InstanceName}_RsCryptomatte.png

The plugin includes repair actions that can fix common naming and configuration issues, making it easier for artists to comply with project naming conventions without manual intervention.

Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
class ValidateGenericRenderSetting(pyblish.api.InstancePlugin,
                                   ValidateRenderSettingsBase):
    """Validate generic render settings before render submission.

    This validator ensures that render output filepaths and filenames
    are correctly configured for the current 3ds Max scene before submission
    to the render farm or local render. It validates the rendering settings
    across multiple supported renderers (V-Ray, Arnold, Redshift, and generic
    renderers) and provides automated repair capabilities.

    The plugin performs the following validation checks:

        1. Render Output Directory Structure
           Validates that the render output folder path matches the expected
           project hierarchy based on the current Max scene filename.
           e.g:
             Current Max scene: John_Doe.max
             Expected output directory:
               {root[work]}/{project[name]}/{hierarchy}/{asset}/
               work/{task[name]}/render/3dsmax/John_Doe/

        2. Image File Extension Compliance
           Ensures that all render output files use the correct image format
           extension as defined in the AYON project settings.
           e.g:
             Configured format in AYON: png
             Expected render outputs: John_Doe.png (and all render elements)
             Invalid outputs: John_Doe.jpg or John_Doe.exr (if format is png)

        3. Render Element Filename Validation
           Checks that each render element output filename follows the naming
           convention and ends with the render element's identifier from the
           3ds Max Render Element Manager.
           e.g.
             Render element name: RsCryptomatte
             Expected filename format: {InstanceName}_RsCryptomatte.png

    The plugin includes repair actions that can fix common naming
    and configuration issues, making it easier for artists to comply with
    project naming conventions without manual intervention.
    """

    order = ValidateContentsOrder
    families = ["maxrender", "renderpreset"]
    hosts = ["max"]
    label = "Validate Generic Render Setting"
    actions = [RepairAction]

    settings_category = "max"

    def process(self, instance: pyblish.api.Instance) -> None:
        """Process the instance to validate generic render settings.

        Args:
            instance (pyblish.api.Instance): The instance to validate.

        Raises:
            PublishValidationError: If any invalid render settings are found.
        """
        renderer, renderer_name = self._get_renderer_data(instance)
        if not self._matches_renderer_name(renderer_name):
            return

        invalid = self._get_invalid_settings(instance, renderer, renderer_name)
        if invalid:
            bullet_point_invalid_statement = "\n".join(
                f"- {err_type}: {filepath}" for err_type, filepath in invalid
            )
            report = (
                "Invalid render passes found.\n\n"
                f"{bullet_point_invalid_statement}\n\n"
                "You can use repair action to fix the invalid filepath."
            )
            raise PublishValidationError(
                report,
                title="Invalid Render Passes",
            )

    @classmethod
    def get_invalid_render_element_directory(
        cls,
        directory: str,
        workfile_pattern: str,
        multi_camera: bool = False,
        cameras: Optional[list[str]] = None,
    ) -> list[tuple[str, str]]:
        """Get the invalid render element directory settings.

        Args:
            directory (str): render directory to validate
            workfile_pattern (str): workfile name pattern to validate
            multi_camera (bool, optional): Whether multi-camera is enabled.
            Defaults to False.
            cameras (Optional[list[str]], optional): The list of camera
                names to validate. Defaults to None.

        Returns:
            list[tuple[str, str]]: A list of tuples containing the error
                type and the invalid directory.
        """
        invalid = []
        if workfile_pattern not in directory:
            msg = (
                f"Invalid render element output directory {directory}. "
                f"Directory should contain the workfile name pattern: {workfile_pattern}."
            )
            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
    def get_invalid_render_settings(
        cls,
        instance: pyblish.api.Instance,
        renderer_name: str,
        workfile_pattern: str,
        renderer: rt.Renderers.current,
        project_settings: dict,
    ) -> list[tuple[str, str]]:
        """Get the invalid render settings.

        Args:
            instance (pyblish.api.Instance): The instance to validate.
            renderer_name (str): The name of the renderer.
            workfile_pattern (str): The workfile name pattern to validate.
            renderer (rt.Renderers.current): The current renderer.
            project_settings (dict): The project settings.

        Returns:
            list[tuple[str, str]]: A list of tuples containing the error
                type and the invalid setting.
        """
        invalid = []
        image_format = instance.data["imageFormat"]
        if renderer_name == "Redshift_Renderer":
            multipass_enabled = get_multipass_setting(
                renderer_name,
                project_settings,
            )
            if renderer.separateAovFiles != multipass_enabled:
                invalid.append((
                    "Invalid Redshift multipass setting",
                    f"Expected: {multipass_enabled}, Found: {renderer.separateAovFiles}",
                ))
            if image_format == "exr" and not renderer.OutputExrMultipart:
                invalid.append((
                    "Invalid Redshift render setting",
                    "EXR image format should have OutputExrMultipart enabled for AOVs.",
                ))

        multicam = instance.data.get("multiCamera", False)
        cameras = instance.data.get("cameras", [])
        invalid.extend(
            cls.get_invalid_renderoutput(
                image_format,
                workfile_pattern,
                multicam=multicam,
                cameras=cameras,
            )
        )

        render_elem = rt.maxOps.GetCurRenderElementMgr()
        render_elem_num = render_elem.NumRenderElements()
        if render_elem_num < 1:
            return invalid

        for index in range(render_elem_num):
            renderlayer = render_elem.GetRenderElement(index)
            if not renderlayer.enabled:
                continue

            render_element_filename = render_elem.GetRenderElementFilename(index)
            invalid.extend(
                cls.get_invalid_render_element_directory(
                    os.path.dirname(render_element_filename),
                    workfile_pattern,
                    multi_camera=multicam,
                    cameras=cameras,
                )
            )
            r_fname = os.path.basename(render_element_filename)
            if not is_general_default_output_regex_matched(r_fname):
                invalid.append((
                    "Invalid render element output filename",
                    "render element output filename does not match the "
                    f"default output regex, Found: {r_fname}",
                ))
            if not r_fname.endswith(f".{image_format}"):
                invalid.append((
                    "Invalid render element output filename",
                    "render element output filename should end with "
                    f".{image_format}, Found: {r_fname}",
                ))
        return invalid

    @classmethod
    def repair(cls, instance: pyblish.api.Instance) -> None:
        renderer, renderer_name = cls._get_renderer_data(instance)
        if not cls._matches_renderer_name(renderer_name):
            return

        if instance.data.get("multiCamera"):
            instance_node = instance.data.get("instance_node")
            project_settings = instance.context.data["project_settings"]
            RenderSettings(project_settings).render_output(instance_node)
            return

        cls.repair_generic_render_settings(instance, renderer_name, renderer)

    @classmethod
    def repair_generic_render_settings(
        cls,
        instance: pyblish.api.Instance,
        renderer_name: str,
        renderer: rt.Renderers.current,
    ) -> None:
        """Repair the generic render settings.

        Args:
            instance (pyblish.api.Instance): The instance to repair.
            renderer_name (str): The name of the renderer.
            renderer (rt.Renderers.current): The current renderer.
        """
        image_format = instance.data["imageFormat"]
        renderoutput = rt.rendOutputFilename
        project_settings = instance.context.data["project_settings"]
        if not renderoutput:
            RenderSettings(project_settings).render_output(
                instance.data.get("instance_node")
            )
            renderoutput = rt.rendOutputFilename

        output_dir = set_correct_workfile_name_for_render_output(
            instance,
            os.path.dirname(renderoutput),
        )
        if renderer_name == "Redshift_Renderer":
            renderer.separateAovFiles = get_multipass_setting(
                renderer_name,
                project_settings,
            )
            if image_format == "exr":
                renderer.OutputExrMultipart = get_multipass_setting(
                    renderer_name,
                    project_settings,
                )

        filename = os.path.basename(renderoutput)
        rt.rendOutputFilename = build_general_output_filename(
            output_dir,
            filename,
        )
        cls.log.info(
            "Render output filename has been repaired to %s",
            rt.rendOutputFilename,
        )

        render_elem = rt.maxOps.GetCurRenderElementMgr()
        render_elem_num = render_elem.NumRenderElements()
        if render_elem_num < 1:
            return

        for index in range(render_elem_num):
            renderlayer = render_elem.GetRenderElement(index)
            if not renderlayer.enabled:
                continue

            render_element_filename = render_elem.GetRenderElementFilename(index)
            r_fname = os.path.basename(render_element_filename)
            output_dir = set_correct_workfile_name_for_render_output(
                instance,
                os.path.dirname(render_element_filename),
            )
            output_filename = build_general_output_filename(output_dir, r_fname)
            render_elem.SetRenderElementFilename(index, output_filename)
            cls.log.info(
                "Render element output filename has been repaired to %s",
                render_elem.GetRenderElementFilename(index),
            )
        rt.renderSceneDialog.update()

get_invalid_render_element_directory(directory, workfile_pattern, multi_camera=False, cameras=None) classmethod

Get the invalid render element directory settings.

Parameters:

Name Type Description Default
directory str

render directory to validate

required
workfile_pattern str

workfile name pattern to validate

required
multi_camera bool

Whether multi-camera is enabled.

False
cameras Optional[list[str]]

The list of camera names to validate. Defaults to None.

None

Returns:

Type Description
list[tuple[str, str]]

list[tuple[str, str]]: A list of tuples containing the error type and the invalid directory.

Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
@classmethod
def get_invalid_render_element_directory(
    cls,
    directory: str,
    workfile_pattern: str,
    multi_camera: bool = False,
    cameras: Optional[list[str]] = None,
) -> list[tuple[str, str]]:
    """Get the invalid render element directory settings.

    Args:
        directory (str): render directory to validate
        workfile_pattern (str): workfile name pattern to validate
        multi_camera (bool, optional): Whether multi-camera is enabled.
        Defaults to False.
        cameras (Optional[list[str]], optional): The list of camera
            names to validate. Defaults to None.

    Returns:
        list[tuple[str, str]]: A list of tuples containing the error
            type and the invalid directory.
    """
    invalid = []
    if workfile_pattern not in directory:
        msg = (
            f"Invalid render element output directory {directory}. "
            f"Directory should contain the workfile name pattern: {workfile_pattern}."
        )
        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

get_invalid_render_settings(instance, renderer_name, workfile_pattern, renderer, project_settings) classmethod

Get the invalid render settings.

Parameters:

Name Type Description Default
instance Instance

The instance to validate.

required
renderer_name str

The name of the renderer.

required
workfile_pattern str

The workfile name pattern to validate.

required
renderer current

The current renderer.

required
project_settings dict

The project settings.

required

Returns:

Type Description
list[tuple[str, str]]

list[tuple[str, str]]: A list of tuples containing the error type and the invalid setting.

Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
@classmethod
def get_invalid_render_settings(
    cls,
    instance: pyblish.api.Instance,
    renderer_name: str,
    workfile_pattern: str,
    renderer: rt.Renderers.current,
    project_settings: dict,
) -> list[tuple[str, str]]:
    """Get the invalid render settings.

    Args:
        instance (pyblish.api.Instance): The instance to validate.
        renderer_name (str): The name of the renderer.
        workfile_pattern (str): The workfile name pattern to validate.
        renderer (rt.Renderers.current): The current renderer.
        project_settings (dict): The project settings.

    Returns:
        list[tuple[str, str]]: A list of tuples containing the error
            type and the invalid setting.
    """
    invalid = []
    image_format = instance.data["imageFormat"]
    if renderer_name == "Redshift_Renderer":
        multipass_enabled = get_multipass_setting(
            renderer_name,
            project_settings,
        )
        if renderer.separateAovFiles != multipass_enabled:
            invalid.append((
                "Invalid Redshift multipass setting",
                f"Expected: {multipass_enabled}, Found: {renderer.separateAovFiles}",
            ))
        if image_format == "exr" and not renderer.OutputExrMultipart:
            invalid.append((
                "Invalid Redshift render setting",
                "EXR image format should have OutputExrMultipart enabled for AOVs.",
            ))

    multicam = instance.data.get("multiCamera", False)
    cameras = instance.data.get("cameras", [])
    invalid.extend(
        cls.get_invalid_renderoutput(
            image_format,
            workfile_pattern,
            multicam=multicam,
            cameras=cameras,
        )
    )

    render_elem = rt.maxOps.GetCurRenderElementMgr()
    render_elem_num = render_elem.NumRenderElements()
    if render_elem_num < 1:
        return invalid

    for index in range(render_elem_num):
        renderlayer = render_elem.GetRenderElement(index)
        if not renderlayer.enabled:
            continue

        render_element_filename = render_elem.GetRenderElementFilename(index)
        invalid.extend(
            cls.get_invalid_render_element_directory(
                os.path.dirname(render_element_filename),
                workfile_pattern,
                multi_camera=multicam,
                cameras=cameras,
            )
        )
        r_fname = os.path.basename(render_element_filename)
        if not is_general_default_output_regex_matched(r_fname):
            invalid.append((
                "Invalid render element output filename",
                "render element output filename does not match the "
                f"default output regex, Found: {r_fname}",
            ))
        if not r_fname.endswith(f".{image_format}"):
            invalid.append((
                "Invalid render element output filename",
                "render element output filename should end with "
                f".{image_format}, Found: {r_fname}",
            ))
    return invalid

process(instance)

Process the instance to validate generic render settings.

Parameters:

Name Type Description Default
instance Instance

The instance to validate.

required

Raises:

Type Description
PublishValidationError

If any invalid render settings are found.

Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def process(self, instance: pyblish.api.Instance) -> None:
    """Process the instance to validate generic render settings.

    Args:
        instance (pyblish.api.Instance): The instance to validate.

    Raises:
        PublishValidationError: If any invalid render settings are found.
    """
    renderer, renderer_name = self._get_renderer_data(instance)
    if not self._matches_renderer_name(renderer_name):
        return

    invalid = self._get_invalid_settings(instance, renderer, renderer_name)
    if invalid:
        bullet_point_invalid_statement = "\n".join(
            f"- {err_type}: {filepath}" for err_type, filepath in invalid
        )
        report = (
            "Invalid render passes found.\n\n"
            f"{bullet_point_invalid_statement}\n\n"
            "You can use repair action to fix the invalid filepath."
        )
        raise PublishValidationError(
            report,
            title="Invalid Render Passes",
        )

repair_generic_render_settings(instance, renderer_name, renderer) classmethod

Repair the generic render settings.

Parameters:

Name Type Description Default
instance Instance

The instance to repair.

required
renderer_name str

The name of the renderer.

required
renderer current

The current renderer.

required
Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
@classmethod
def repair_generic_render_settings(
    cls,
    instance: pyblish.api.Instance,
    renderer_name: str,
    renderer: rt.Renderers.current,
) -> None:
    """Repair the generic render settings.

    Args:
        instance (pyblish.api.Instance): The instance to repair.
        renderer_name (str): The name of the renderer.
        renderer (rt.Renderers.current): The current renderer.
    """
    image_format = instance.data["imageFormat"]
    renderoutput = rt.rendOutputFilename
    project_settings = instance.context.data["project_settings"]
    if not renderoutput:
        RenderSettings(project_settings).render_output(
            instance.data.get("instance_node")
        )
        renderoutput = rt.rendOutputFilename

    output_dir = set_correct_workfile_name_for_render_output(
        instance,
        os.path.dirname(renderoutput),
    )
    if renderer_name == "Redshift_Renderer":
        renderer.separateAovFiles = get_multipass_setting(
            renderer_name,
            project_settings,
        )
        if image_format == "exr":
            renderer.OutputExrMultipart = get_multipass_setting(
                renderer_name,
                project_settings,
            )

    filename = os.path.basename(renderoutput)
    rt.rendOutputFilename = build_general_output_filename(
        output_dir,
        filename,
    )
    cls.log.info(
        "Render output filename has been repaired to %s",
        rt.rendOutputFilename,
    )

    render_elem = rt.maxOps.GetCurRenderElementMgr()
    render_elem_num = render_elem.NumRenderElements()
    if render_elem_num < 1:
        return

    for index in range(render_elem_num):
        renderlayer = render_elem.GetRenderElement(index)
        if not renderlayer.enabled:
            continue

        render_element_filename = render_elem.GetRenderElementFilename(index)
        r_fname = os.path.basename(render_element_filename)
        output_dir = set_correct_workfile_name_for_render_output(
            instance,
            os.path.dirname(render_element_filename),
        )
        output_filename = build_general_output_filename(output_dir, r_fname)
        render_elem.SetRenderElementFilename(index, output_filename)
        cls.log.info(
            "Render element output filename has been repaired to %s",
            render_elem.GetRenderElementFilename(index),
        )
    rt.renderSceneDialog.update()

ValidateVrayRenderSetting

Bases: ValidateGenericRenderSetting

Validate V-Ray render settings before render submission.

This validator extends the generic render setting validation with V-Ray-specific checks. It keeps the shared validation inherited from :class:ValidateGenericRenderSetting, such as validating the beauty output path, render element output directories, file naming patterns, and image extension consistency, and adds checks for the V-Ray output configuration that is required for AYON publishing.

The plugin performs the following V-Ray-specific validation checks:

 1. V-Ray Multipass Configuration
     Validates that ``output_splitgbuffer`` matches the multipass
     expectation from the AYON project settings.

 2. Raw Output Filename Validation
     When the configured image format is ``exr``, validates that the
     V-Ray raw output filename is defined, points to the expected
     workfile-based output directory, and uses the expected extension.

 3. Split Channel Output Validation
     When multipass rendering is enabled, validates that the split
     output filename is configured correctly and follows the expected
     naming pattern for the current scene.

 4. Beauty Output Fallback Validation
     When multipass rendering is disabled, falls back to validating the
     standard beauty output path using the shared generic validation.

The repair action updates the V-Ray output configuration to match the project settings and rebuilds invalid output filenames so artists can fix common publish issues directly from the validator.

Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
class ValidateVrayRenderSetting(ValidateGenericRenderSetting):
    """Validate V-Ray render settings before render submission.

     This validator extends the generic render setting validation with
     V-Ray-specific checks. It keeps the shared validation inherited from
     :class:`ValidateGenericRenderSetting`, such as validating the beauty
     output path, render element output directories, file naming patterns,
     and image extension consistency, and adds checks for the V-Ray output
     configuration that is required for AYON publishing.

     The plugin performs the following V-Ray-specific validation checks:

          1. V-Ray Multipass Configuration
              Validates that ``output_splitgbuffer`` matches the multipass
              expectation from the AYON project settings.

          2. Raw Output Filename Validation
              When the configured image format is ``exr``, validates that the
              V-Ray raw output filename is defined, points to the expected
              workfile-based output directory, and uses the expected extension.

          3. Split Channel Output Validation
              When multipass rendering is enabled, validates that the split
              output filename is configured correctly and follows the expected
              naming pattern for the current scene.

          4. Beauty Output Fallback Validation
              When multipass rendering is disabled, falls back to validating the
              standard beauty output path using the shared generic validation.

     The repair action updates the V-Ray output configuration to match the
     project settings and rebuilds invalid output filenames so artists can
     fix common publish issues directly from the validator.

    """

    label = "Validate Vray Render Setting"

    @classmethod
    def _matches_renderer_name(cls, renderer_name: str) -> bool:
        """Check if the renderer name matches the supported renderers.

        Args:
            renderer_name (str): The name of the renderer to check.

        Returns:
            bool: True if the renderer is supported, False otherwise.
        """
        return renderer_name.startswith("V_Ray_")

    @classmethod
    def get_invalid_vray_filepaths(
        cls,
        render_filepath: str,
        extension: str,
        workfile_pattern: str,
    ) -> list[tuple[str, str]]:
        """Get invalid V-Ray filepaths for the given instance.

        Args:
            render_filepath (str): The render output filepath.
            extension (str): The expected file extension.
            workfile_pattern (str): The workfile name pattern.

        Returns:
            list[tuple[str, str]]: A list of tuples containing error messages and invalid values.
        """
        invalid = []
        render_dir = os.path.dirname(render_filepath)
        render_filename = os.path.basename(render_filepath)
        if workfile_pattern not in render_dir:
            msg = (
                f"Invalid render output filename {render_filename} for V-Ray. "
                f"Filename should contain the workfile name pattern: {workfile_pattern}."
            )
            cls.log.error(msg)
            invalid.append((msg, render_dir))
        if ".." in render_filename:
            msg = (
                f"Invalid render output filename {render_filename} for V-Ray "
                "Filename should not contain double dots."
            )
            cls.log.error(msg)
            invalid.append((msg, render_filename))
        if not render_filename.endswith(f".{extension}"):
            msg = (
                f"Invalid render output filename {render_filename} for V-Ray "
                f"Filename should end with .{extension}."
            )
            cls.log.error(msg)
            invalid.append((msg, render_filename))

        return invalid

    @classmethod
    def _get_invalid_vray_output(
        cls,
        filepath: str,
        extension: str,
        workfile_pattern: str,
    ) -> list[tuple[str, str]]:
        """Get invalid V-Ray output settings for the given instance.

        Args:
            filepath (str): The render output filepath.
            extension (str): The expected file extension.
            workfile_pattern (str): The workfile name pattern.

        Returns:
            list[tuple[str, str]]: A list of tuples containing error
                messages and invalid values.
        """
        if not filepath:
            message = (
                "V-Ray output filepath is empty. "
                "Please set it in render settings."
            )
            cls.log.error(message)
            return [(message, filepath)]

        return cls.get_invalid_vray_filepaths(
            filepath,
            extension,
            workfile_pattern,
        )

    @classmethod
    def get_invalid_render_settings(
        cls,
        instance: pyblish.api.Instance,
        renderer_name: str,
        workfile_pattern: str,
        renderer: rt.Renderers.current,
        project_settings: dict,
    ) -> list[tuple[str, str]]:
        """Get invalid V-Ray settings for the given instance.

        Args:
            instance (pyblish.api.Instance): The instance to validate.
            renderer_name (str): The name of the renderer.
            workfile_pattern (str): The workfile name pattern.
            renderer (rt.Renderers.current): The current renderer.
            project_settings (dict): The project settings dictionary.

        Returns:
            list[tuple[str, str]]: A list of tuples containing error messages
                and invalid values.
        """
        invalid = []
        vr_settings = get_vray_settings(renderer_name, renderer)
        image_format = instance.data["imageFormat"]
        multipass_enabled = get_multipass_setting(renderer_name, project_settings)
        if multipass_enabled != vr_settings.output_splitgbuffer:
            invalid.append((
                "Invalid V-Ray multipass setting",
                f"Expected: {multipass_enabled}, Found: {vr_settings.output_splitgbuffer}",
            ))

        if image_format == "exr":
            invalid.extend(
                cls._get_invalid_vray_output(
                    vr_settings.output_rawfilename,
                    image_format,
                    workfile_pattern,
                )
            )

        if multipass_enabled:
            invalid.extend(
                cls._get_invalid_vray_output(
                    vr_settings.output_splitfilename,
                    image_format,
                    workfile_pattern,
                )
            )
        else:
            invalid.extend(
                cls.get_invalid_renderoutput(image_format, workfile_pattern)
            )

        return invalid

    @classmethod
    def repair(cls, instance: pyblish.api.Instance) -> None:
        """Repair invalid V-Ray render settings for the given instance.

        Args:
            instance (pyblish.api.Instance): instance to repair
        """
        renderer, renderer_name = cls._get_renderer_data(instance)
        if not cls._matches_renderer_name(renderer_name):
            return
        vr_settings = get_vray_settings(renderer_name, renderer)
        cls.repair_vray_settings(
            instance,
            renderer_name,
            vr_settings,
        )

    @classmethod
    def repair_vray_settings(
        cls,
        instance: pyblish.api.Instance,
        renderer_name: str,
        vr_settings: Any,
    ) -> None:
        """Repair V-Ray settings for the given instance.

        Args:
            instance (pyblish.api.Instance): The instance to repair.
            renderer_name (str): The name of the renderer.
            vr_settings (Any): The V-Ray settings object.
        """
        image_format = instance.data["imageFormat"]
        project_settings = instance.context.data["project_settings"]
        multipass_enabled = get_multipass_setting(renderer_name, project_settings)
        vr_settings.output_splitgbuffer = multipass_enabled

        if image_format == "exr":
            vr_settings.output_rawfilename = cls._repair_vray_output_filename(
                vr_settings.output_rawfilename,
                image_format,
                instance,
            )
        if multipass_enabled:
            vr_settings.output_splitfilename = cls._repair_vray_output_filename(
                vr_settings.output_splitfilename,
                image_format,
                instance,
            )

    @classmethod
    def _repair_vray_output_filename(
        cls,
        filename: str,
        image_format: str,
        instance: pyblish.api.Instance,
    ) -> str:
        """Repair the V-Ray output filename for the given instance.

        Args:
            filename (str): The current V-Ray output filename.
            image_format (str): The image format for the output file.
            instance (pyblish.api.Instance): The instance being processed.

        Returns:
            str: The repaired V-Ray output filename.
        """
        instance_node = instance.data.get("instance_node")
        project_settings = instance.context.data["project_settings"]
        if not filename:
            RenderSettings(project_settings).render_output(instance_node)
            filename = rt.rendOutputFilename

        output_dir = set_correct_workfile_name_for_render_output(
            instance,
            os.path.dirname(filename),
        )
        output_filename = os.path.basename(filename)
        return cls._build_vray_output_filename(
            output_dir,
            output_filename,
            image_format,
        )

    @classmethod
    def _build_vray_output_filename(
        cls,
        output_dir: str,
        filename: str,
        image_format: str,
    ) -> str:
        """Build the full path for the V-Ray output file.

        Args:
            output_dir (str): The directory where the output file will be saved.
            filename (str): The name of the output file.
            image_format (str): The image format for the output file.

        Returns:
            str: The full path to the repaired V-Ray output file.
        """
        name = os.path.splitext(filename)[0].lstrip(".")
        output_filename = f"{name}.{image_format}"
        return os.path.join(output_dir, output_filename)

get_invalid_render_settings(instance, renderer_name, workfile_pattern, renderer, project_settings) classmethod

Get invalid V-Ray settings for the given instance.

Parameters:

Name Type Description Default
instance Instance

The instance to validate.

required
renderer_name str

The name of the renderer.

required
workfile_pattern str

The workfile name pattern.

required
renderer current

The current renderer.

required
project_settings dict

The project settings dictionary.

required

Returns:

Type Description
list[tuple[str, str]]

list[tuple[str, str]]: A list of tuples containing error messages and invalid values.

Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
@classmethod
def get_invalid_render_settings(
    cls,
    instance: pyblish.api.Instance,
    renderer_name: str,
    workfile_pattern: str,
    renderer: rt.Renderers.current,
    project_settings: dict,
) -> list[tuple[str, str]]:
    """Get invalid V-Ray settings for the given instance.

    Args:
        instance (pyblish.api.Instance): The instance to validate.
        renderer_name (str): The name of the renderer.
        workfile_pattern (str): The workfile name pattern.
        renderer (rt.Renderers.current): The current renderer.
        project_settings (dict): The project settings dictionary.

    Returns:
        list[tuple[str, str]]: A list of tuples containing error messages
            and invalid values.
    """
    invalid = []
    vr_settings = get_vray_settings(renderer_name, renderer)
    image_format = instance.data["imageFormat"]
    multipass_enabled = get_multipass_setting(renderer_name, project_settings)
    if multipass_enabled != vr_settings.output_splitgbuffer:
        invalid.append((
            "Invalid V-Ray multipass setting",
            f"Expected: {multipass_enabled}, Found: {vr_settings.output_splitgbuffer}",
        ))

    if image_format == "exr":
        invalid.extend(
            cls._get_invalid_vray_output(
                vr_settings.output_rawfilename,
                image_format,
                workfile_pattern,
            )
        )

    if multipass_enabled:
        invalid.extend(
            cls._get_invalid_vray_output(
                vr_settings.output_splitfilename,
                image_format,
                workfile_pattern,
            )
        )
    else:
        invalid.extend(
            cls.get_invalid_renderoutput(image_format, workfile_pattern)
        )

    return invalid

get_invalid_vray_filepaths(render_filepath, extension, workfile_pattern) classmethod

Get invalid V-Ray filepaths for the given instance.

Parameters:

Name Type Description Default
render_filepath str

The render output filepath.

required
extension str

The expected file extension.

required
workfile_pattern str

The workfile name pattern.

required

Returns:

Type Description
list[tuple[str, str]]

list[tuple[str, str]]: A list of tuples containing error messages and invalid values.

Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
@classmethod
def get_invalid_vray_filepaths(
    cls,
    render_filepath: str,
    extension: str,
    workfile_pattern: str,
) -> list[tuple[str, str]]:
    """Get invalid V-Ray filepaths for the given instance.

    Args:
        render_filepath (str): The render output filepath.
        extension (str): The expected file extension.
        workfile_pattern (str): The workfile name pattern.

    Returns:
        list[tuple[str, str]]: A list of tuples containing error messages and invalid values.
    """
    invalid = []
    render_dir = os.path.dirname(render_filepath)
    render_filename = os.path.basename(render_filepath)
    if workfile_pattern not in render_dir:
        msg = (
            f"Invalid render output filename {render_filename} for V-Ray. "
            f"Filename should contain the workfile name pattern: {workfile_pattern}."
        )
        cls.log.error(msg)
        invalid.append((msg, render_dir))
    if ".." in render_filename:
        msg = (
            f"Invalid render output filename {render_filename} for V-Ray "
            "Filename should not contain double dots."
        )
        cls.log.error(msg)
        invalid.append((msg, render_filename))
    if not render_filename.endswith(f".{extension}"):
        msg = (
            f"Invalid render output filename {render_filename} for V-Ray "
            f"Filename should end with .{extension}."
        )
        cls.log.error(msg)
        invalid.append((msg, render_filename))

    return invalid

repair(instance) classmethod

Repair invalid V-Ray render settings for the given instance.

Parameters:

Name Type Description Default
instance Instance

instance to repair

required
Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
@classmethod
def repair(cls, instance: pyblish.api.Instance) -> None:
    """Repair invalid V-Ray render settings for the given instance.

    Args:
        instance (pyblish.api.Instance): instance to repair
    """
    renderer, renderer_name = cls._get_renderer_data(instance)
    if not cls._matches_renderer_name(renderer_name):
        return
    vr_settings = get_vray_settings(renderer_name, renderer)
    cls.repair_vray_settings(
        instance,
        renderer_name,
        vr_settings,
    )

repair_vray_settings(instance, renderer_name, vr_settings) classmethod

Repair V-Ray settings for the given instance.

Parameters:

Name Type Description Default
instance Instance

The instance to repair.

required
renderer_name str

The name of the renderer.

required
vr_settings Any

The V-Ray settings object.

required
Source code in client/ayon_max/plugins/publish/validate_rendersettings.py
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
@classmethod
def repair_vray_settings(
    cls,
    instance: pyblish.api.Instance,
    renderer_name: str,
    vr_settings: Any,
) -> None:
    """Repair V-Ray settings for the given instance.

    Args:
        instance (pyblish.api.Instance): The instance to repair.
        renderer_name (str): The name of the renderer.
        vr_settings (Any): The V-Ray settings object.
    """
    image_format = instance.data["imageFormat"]
    project_settings = instance.context.data["project_settings"]
    multipass_enabled = get_multipass_setting(renderer_name, project_settings)
    vr_settings.output_splitgbuffer = multipass_enabled

    if image_format == "exr":
        vr_settings.output_rawfilename = cls._repair_vray_output_filename(
            vr_settings.output_rawfilename,
            image_format,
            instance,
        )
    if multipass_enabled:
        vr_settings.output_splitfilename = cls._repair_vray_output_filename(
            vr_settings.output_splitfilename,
            image_format,
            instance,
        )