Skip to content

validate_ass_relative_paths

ValidateAssRelativePaths

Bases: MayaInstancePlugin, OptionalPyblishPluginMixin

Ensure exporting ass file has set relative texture paths

Source code in client/ayon_maya/plugins/publish/validate_ass_relative_paths.py
 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
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
class ValidateAssRelativePaths(plugin.MayaInstancePlugin,
                               OptionalPyblishPluginMixin):
    """Ensure exporting ass file has set relative texture paths"""

    order = ValidateContentsOrder
    families = ['ass']
    label = "ASS has relative texture paths"
    actions = [RepairAction]
    optional = False

    def process(self, instance):
        if not self.is_active(instance.data):
            return
        # we cannot ask this until user open render settings as
        # `defaultArnoldRenderOptions` doesn't exist
        errors = []

        try:
            absolute_texture = cmds.getAttr(
                "defaultArnoldRenderOptions.absolute_texture_paths")
            absolute_procedural = cmds.getAttr(
                "defaultArnoldRenderOptions.absolute_procedural_paths")
            texture_search_path = cmds.getAttr(
                "defaultArnoldRenderOptions.tspath"
            )
            procedural_search_path = cmds.getAttr(
                "defaultArnoldRenderOptions.pspath"
            )
        except ValueError:
            raise PublishValidationError(
                "Default Arnold options has not been created yet."
            )

        scene_dir, scene_basename = os.path.split(cmds.file(q=True, loc=True))
        scene_name, _ = os.path.splitext(scene_basename)

        if self.maya_is_true(absolute_texture):
            errors.append("Texture path is set to be absolute")
        if self.maya_is_true(absolute_procedural):
            errors.append("Procedural path is set to be absolute")

        anatomy = instance.context.data["anatomy"]

        # Use project root variables for multiplatform support, see:
        # https://docs.arnoldrenderer.com/display/A5AFMUG/Search+Path
        # ':' as path separator is supported by Arnold for all platforms.
        keys = anatomy.root_environments().keys()
        paths = []
        for k in keys:
            paths.append("[{}]".format(k))

        self.log.debug("discovered roots: {}".format(":".join(paths)))

        if ":".join(paths) not in texture_search_path:
            errors.append((
                "Project roots {} are not in texture_search_path: {}"
            ).format(paths, texture_search_path))

        if ":".join(paths) not in procedural_search_path:
            errors.append((
                "Project roots {} are not in procedural_search_path: {}"
            ).format(paths, procedural_search_path))

        if errors:
            errors = "\n".join(f"- {error}" for error in errors)
            raise PublishValidationError(errors,
                                         description=self.get_description())

    @classmethod
    def repair(cls, instance):
        createOptions()

        texture_path = cmds.getAttr("defaultArnoldRenderOptions.tspath")
        procedural_path = cmds.getAttr("defaultArnoldRenderOptions.pspath")

        # Use project root variables for multiplatform support, see:
        # https://docs.arnoldrenderer.com/display/A5AFMUG/Search+Path
        # ':' as path separator is supported by Arnold for all platforms.
        anatomy = instance.context.data["anatomy"]
        keys = anatomy.root_environments().keys()
        paths = []
        for k in keys:
            paths.append("[{}]".format(k))

        cmds.setAttr(
            "defaultArnoldRenderOptions.tspath",
            ":".join([p for p in paths + [texture_path] if p]),
            type="string"
        )
        cmds.setAttr(
            "defaultArnoldRenderOptions.absolute_texture_paths",
            False
        )

        cmds.setAttr(
            "defaultArnoldRenderOptions.pspath",
            ":".join([p for p in paths + [procedural_path] if p]),
            type="string"
        )
        cmds.setAttr(
            "defaultArnoldRenderOptions.absolute_procedural_paths",
            False
        )

    @staticmethod
    def find_absolute_path(relative_path, all_root_paths):
        for root_path in all_root_paths:
            possible_path = os.path.join(root_path, relative_path)
            if os.path.exists(possible_path):
                return possible_path

    def maya_is_true(self, attr_val):
        """
        Whether a Maya attr evaluates to True.
        When querying an attribute value from an ambiguous object the
        Maya API will return a list of values, which need to be properly
        handled to evaluate properly.
        """
        if isinstance(attr_val, bool):
            return attr_val
        elif isinstance(attr_val, (list, types.GeneratorType)):
            return any(attr_val)
        else:
            return bool(attr_val)

    def get_description(self):
        return inspect.cleandoc("""
            ### ASS must have relative texture paths

            The Arnold Render Settings must be set to:

            - Texture paths must be relative
            - Procedural paths must be relative
            - Texture search path must include the project roots
            - Procedural search path must include the project roots

            By enforcing this, the textures can be remapped correctly depending
            on where the project might be located on another OS or machine like
            a renderfarm.

            The settings are in the `Render Settings > System > Search Paths`
            section.

            ### Repair

            Using **Repair** will set the required render settings for you.
        """)

maya_is_true(attr_val)

Whether a Maya attr evaluates to True. When querying an attribute value from an ambiguous object the Maya API will return a list of values, which need to be properly handled to evaluate properly.

Source code in client/ayon_maya/plugins/publish/validate_ass_relative_paths.py
128
129
130
131
132
133
134
135
136
137
138
139
140
def maya_is_true(self, attr_val):
    """
    Whether a Maya attr evaluates to True.
    When querying an attribute value from an ambiguous object the
    Maya API will return a list of values, which need to be properly
    handled to evaluate properly.
    """
    if isinstance(attr_val, bool):
        return attr_val
    elif isinstance(attr_val, (list, types.GeneratorType)):
        return any(attr_val)
    else:
        return bool(attr_val)