Skip to content

validate_renderlayer_active

ValidateRenderlayerActive

Bases: BlenderContextPlugin

Validate the state of view layers based on the instance's view layer definitions. If a view layer is expected to be active but is inactive, it will be flagged as invalid. Repair action would fix this issue by setting the view layers to their expected states according to the instance's definitions.

Source code in client/ayon_blender/plugins/publish/validate_renderlayer_active.py
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 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
class ValidateRenderlayerActive(plugin.BlenderContextPlugin):
    """Validate the state of view layers based on the instance's view layer
    definitions. If a view layer is expected to be active but is inactive, it
    will be flagged as invalid. Repair action would fix this issue by setting
    the view layers to their expected states according to the instance's
    definitions.
    """

    order = pyblish.api.ValidatorOrder
    hosts = ["blender"]
    label = "Validate Renderlayer Active"
    actions = [RepairContextAction]

    def process(self, context: pyblish.api.Context) -> None:
        """
        Validate the state of view layers based on the instance's view layer

        Args:
            context (pyblish.api.Context): Context data
        """
        enabled_compositor_nodes = self.get_enabled_compositor_nodes(context)
        if not enabled_compositor_nodes:
            # No render instances enabled, nothing to validate
            return

        invalid = self.get_invalid(enabled_compositor_nodes)
        if invalid:
            raise PublishValidationError(
                "Some view layers are not in the expected state.",
                title="Invalid view layer states",
                description=self.get_description(),
            )

    @staticmethod
    def get_enabled_compositor_nodes(
        context: pyblish.api.Context
    ) -> set["bpy.types.CompositorNodeOutputFile"]:
        """Return Compositor File Output nodes that are associated with
        enabled render instances."""
        nodes = set()
        for instance in context:
            # Process only render instances
            if instance.data["productBaseType"] != "render":
                continue
            # Skip disabled instances
            if not instance.data.get("active", True):
                continue
            comp_output_node: "bpy.types.CompositorNodeOutputFile" = (
                instance.data["transientData"]["instance_node"]
            )
            nodes.add(comp_output_node)
        return nodes

    @classmethod
    def get_invalid(
        cls,
        enabled_compositor_nodes: set["bpy.types.CompositorNodeOutputFile"]
    ) -> list[bpy.types.ViewLayer]:
        """Get the list of invalid view layers based on the instance's view
        layer definitions.

        Args:
            enabled_compositor_nodes: Compositor File Output nodes that
                are associated with enabled render instances.

        Returns:
            list[bpy.types.ViewLayer]: A list of invalid view layers.
        """

        required_viewlayers = set()
        for comp_output_node in enabled_compositor_nodes:
            used_viewlayers = lib.get_upstream_viewlayers(comp_output_node)
            required_viewlayers.update(used_viewlayers)

        invalid = []
        for viewlayer in bpy.context.scene.view_layers:
            is_required = viewlayer.name in required_viewlayers
            if viewlayer.use != is_required:
                active_label = "active" if viewlayer.use else "inactive"
                required_label = "active" if is_required else "inactive"

                cls.log.error(
                    f"View layer '{viewlayer.name}' should be {required_label}"
                    f" but is currently {active_label}."
                )
                invalid.append(viewlayer)

        return invalid

    @classmethod
    def repair(cls, context: pyblish.api.Context) -> None:
        """Repair the state of view layers based on the instance's
        view layer definitions.

        Args:
            context (pyblish.api.Context): Context data

        """
        enabled_compositor_nodes = cls.get_enabled_compositor_nodes(context)
        invalid = cls.get_invalid(enabled_compositor_nodes)
        for viewlayer in invalid:
            # Toggle from the invalid state
            viewlayer.use = not viewlayer.use

    def get_description(self):
        return inspect.cleandoc(
            """### Disabled view layers are required for rendering
            Some view layers are disabled while being used for rendering outputs
            through File Output nodes.
            The repair action will enable them for rendering,
            ensuring valid outputs are produced once submitted.
            """
    )

get_enabled_compositor_nodes(context) staticmethod

Return Compositor File Output nodes that are associated with enabled render instances.

Source code in client/ayon_blender/plugins/publish/validate_renderlayer_active.py
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@staticmethod
def get_enabled_compositor_nodes(
    context: pyblish.api.Context
) -> set["bpy.types.CompositorNodeOutputFile"]:
    """Return Compositor File Output nodes that are associated with
    enabled render instances."""
    nodes = set()
    for instance in context:
        # Process only render instances
        if instance.data["productBaseType"] != "render":
            continue
        # Skip disabled instances
        if not instance.data.get("active", True):
            continue
        comp_output_node: "bpy.types.CompositorNodeOutputFile" = (
            instance.data["transientData"]["instance_node"]
        )
        nodes.add(comp_output_node)
    return nodes

get_invalid(enabled_compositor_nodes) classmethod

Get the list of invalid view layers based on the instance's view layer definitions.

Parameters:

Name Type Description Default
enabled_compositor_nodes set[CompositorNodeOutputFile]

Compositor File Output nodes that are associated with enabled render instances.

required

Returns:

Type Description
list[ViewLayer]

list[bpy.types.ViewLayer]: A list of invalid view layers.

Source code in client/ayon_blender/plugins/publish/validate_renderlayer_active.py
 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
@classmethod
def get_invalid(
    cls,
    enabled_compositor_nodes: set["bpy.types.CompositorNodeOutputFile"]
) -> list[bpy.types.ViewLayer]:
    """Get the list of invalid view layers based on the instance's view
    layer definitions.

    Args:
        enabled_compositor_nodes: Compositor File Output nodes that
            are associated with enabled render instances.

    Returns:
        list[bpy.types.ViewLayer]: A list of invalid view layers.
    """

    required_viewlayers = set()
    for comp_output_node in enabled_compositor_nodes:
        used_viewlayers = lib.get_upstream_viewlayers(comp_output_node)
        required_viewlayers.update(used_viewlayers)

    invalid = []
    for viewlayer in bpy.context.scene.view_layers:
        is_required = viewlayer.name in required_viewlayers
        if viewlayer.use != is_required:
            active_label = "active" if viewlayer.use else "inactive"
            required_label = "active" if is_required else "inactive"

            cls.log.error(
                f"View layer '{viewlayer.name}' should be {required_label}"
                f" but is currently {active_label}."
            )
            invalid.append(viewlayer)

    return invalid

process(context)

Validate the state of view layers based on the instance's view layer

Parameters:

Name Type Description Default
context Context

Context data

required
Source code in client/ayon_blender/plugins/publish/validate_renderlayer_active.py
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
def process(self, context: pyblish.api.Context) -> None:
    """
    Validate the state of view layers based on the instance's view layer

    Args:
        context (pyblish.api.Context): Context data
    """
    enabled_compositor_nodes = self.get_enabled_compositor_nodes(context)
    if not enabled_compositor_nodes:
        # No render instances enabled, nothing to validate
        return

    invalid = self.get_invalid(enabled_compositor_nodes)
    if invalid:
        raise PublishValidationError(
            "Some view layers are not in the expected state.",
            title="Invalid view layer states",
            description=self.get_description(),
        )

repair(context) classmethod

Repair the state of view layers based on the instance's view layer definitions.

Parameters:

Name Type Description Default
context Context

Context data

required
Source code in client/ayon_blender/plugins/publish/validate_renderlayer_active.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
@classmethod
def repair(cls, context: pyblish.api.Context) -> None:
    """Repair the state of view layers based on the instance's
    view layer definitions.

    Args:
        context (pyblish.api.Context): Context data

    """
    enabled_compositor_nodes = cls.get_enabled_compositor_nodes(context)
    invalid = cls.get_invalid(enabled_compositor_nodes)
    for viewlayer in invalid:
        # Toggle from the invalid state
        viewlayer.use = not viewlayer.use