Skip to content

validate_look_contents

ValidateLookContents

Bases: MayaInstancePlugin

Validate look instance contents

Rules
  • Look data must have relationships and attributes keys.
  • At least one relationship must be collection.
  • All relationship object sets at least have an ID value
Tip
  • When no node IDs are found on shadingEngines please save your scene and try again.
Source code in client/ayon_maya/plugins/publish/validate_look_contents.py
 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
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
class ValidateLookContents(plugin.MayaInstancePlugin):
    """Validate look instance contents

    Rules:
        * Look data must have `relationships` and `attributes` keys.
        * At least one relationship must be collection.
        * All relationship object sets at least have an ID value

    Tip:
        * When no node IDs are found on shadingEngines please save your scene
        and try again.

    """

    order = ValidateContentsOrder
    families = ['look']
    label = 'Look Data Contents'
    actions = [ayon_maya.api.action.SelectInvalidAction]

    def process(self, instance: pyblish.api.Instance):
        """Process all the nodes in the instance"""

        if not instance[:]:
            raise PublishValidationError(
                "Instance is empty", description=self.get_description())
        invalid = self.get_invalid(instance)
        if invalid:
            raise PublishValidationError(
                f"'{instance.name}' has invalid look content",
                description=self.get_description())

    @classmethod
    def get_invalid(cls, instance: pyblish.api.Instance) -> List[str]:
        """Get all invalid nodes"""

        # check if data has the right attributes and content
        attributes = cls.validate_lookdata_attributes(instance)
        # check the looks for ID
        looks = cls.validate_looks(instance)

        invalid = looks + attributes
        return invalid

    @classmethod
    def validate_lookdata_attributes(
            cls, instance: pyblish.api.Instance) -> List[str]:
        """Check if the lookData has the required attributes"""

        invalid = set()

        keys = ["relationships", "attributes"]
        lookdata = instance.data["lookData"]
        for key in keys:
            if key not in lookdata:
                cls.log.error(f"Look Data has no key '{key}'")
                invalid.add(instance.name)

        # Validate at least one single relationship is collected
        if not lookdata["relationships"]:
            cls.log.error(
                "Look '%s' has no relationships. This usually indicates that "
                "geometry or shaders are lacking the required 'cbId'. "
                "Re-save your scene, try again. If still an issue investigate "
                "the attributes on the meshes or shaders." % instance.name)
            invalid.add(instance.name)

        # Check if attributes are on a node with an ID, crucial for rebuild!
        for attr_changes in lookdata["attributes"]:
            if not attr_changes["uuid"] and not attr_changes["attributes"]:
                cls.log.error("Node '%s' has no cbId, please set the "
                              "attributes to its children if it has any."
                              % attr_changes["name"])
                invalid.add(instance.name)

        return list(invalid)

    @classmethod
    def validate_looks(cls, instance: pyblish.api.Instance) -> List[str]:

        looks = instance.data["lookData"]["relationships"]
        invalid = []

        # Ignore objects that are default objects, like e.g. default shading
        # engines because those should be captured by other validators.
        ignored_defaults = set(cmds.ls(defaultNodes=True))

        for name, data in looks.items():
            if name in ignored_defaults:
                cls.log.warning(f"Ignoring default node without UUID '{name}'")
                continue

            if not data["uuid"]:
                cls.log.error("Look '{}' has no UUID".format(name))
                invalid.append(name)

        return invalid

    @classmethod
    def validate_renderer(cls, instance: pyblish.api.Instance):
        # TODO: Rewrite this to be more specific and configurable
        renderer = cmds.getAttr(
            'defaultRenderGlobals.currentRenderer').lower()
        do_maketx = instance.data.get("maketx", False)
        do_rstex = instance.data.get("rstex", False)
        processors = []

        if do_maketx:
            processors.append('arnold')
        if do_rstex:
            processors.append('redshift')

        for processor in processors:
            if processor == renderer:
                continue
            else:
                cls.log.error(
                    "Converted texture does not match current renderer.")

    @staticmethod
    def get_description() -> str:
        return inspect.cleandoc("""
            ## Invalid look contents

            This validator does a general validation on the look contents and
            settings.

            Common issues:

            - The look must have geometry members.
            - All shader and set relationships must have valid `cbId` 
              attributes so that they can be correctly applied elsewhere.

            #### Issues with cbId attributes

            The most common issue here is the `cbId` attribute being invalid.
            These IDs get generated on scene save (on non-referenced nodes) so
            a good first step is usually saving your scene, and trying again.
            If it still fails, then likely you have referenced nodes that do
            not have a valid `cbId`. This should usually be fixed in the scene
            from which that geometry or shader was initially created.
        """)

get_invalid(instance) classmethod

Get all invalid nodes

Source code in client/ayon_maya/plugins/publish/validate_look_contents.py
46
47
48
49
50
51
52
53
54
55
56
@classmethod
def get_invalid(cls, instance: pyblish.api.Instance) -> List[str]:
    """Get all invalid nodes"""

    # check if data has the right attributes and content
    attributes = cls.validate_lookdata_attributes(instance)
    # check the looks for ID
    looks = cls.validate_looks(instance)

    invalid = looks + attributes
    return invalid

process(instance)

Process all the nodes in the instance

Source code in client/ayon_maya/plugins/publish/validate_look_contents.py
34
35
36
37
38
39
40
41
42
43
44
def process(self, instance: pyblish.api.Instance):
    """Process all the nodes in the instance"""

    if not instance[:]:
        raise PublishValidationError(
            "Instance is empty", description=self.get_description())
    invalid = self.get_invalid(instance)
    if invalid:
        raise PublishValidationError(
            f"'{instance.name}' has invalid look content",
            description=self.get_description())

validate_lookdata_attributes(instance) classmethod

Check if the lookData has the required attributes

Source code in client/ayon_maya/plugins/publish/validate_look_contents.py
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
@classmethod
def validate_lookdata_attributes(
        cls, instance: pyblish.api.Instance) -> List[str]:
    """Check if the lookData has the required attributes"""

    invalid = set()

    keys = ["relationships", "attributes"]
    lookdata = instance.data["lookData"]
    for key in keys:
        if key not in lookdata:
            cls.log.error(f"Look Data has no key '{key}'")
            invalid.add(instance.name)

    # Validate at least one single relationship is collected
    if not lookdata["relationships"]:
        cls.log.error(
            "Look '%s' has no relationships. This usually indicates that "
            "geometry or shaders are lacking the required 'cbId'. "
            "Re-save your scene, try again. If still an issue investigate "
            "the attributes on the meshes or shaders." % instance.name)
        invalid.add(instance.name)

    # Check if attributes are on a node with an ID, crucial for rebuild!
    for attr_changes in lookdata["attributes"]:
        if not attr_changes["uuid"] and not attr_changes["attributes"]:
            cls.log.error("Node '%s' has no cbId, please set the "
                          "attributes to its children if it has any."
                          % attr_changes["name"])
            invalid.add(instance.name)

    return list(invalid)

ValidateLookContentsFiles

Bases: MayaInstancePlugin

Validate look resources have valid files.

Rules
  • Look data must have relationships and attributes keys.
  • At least one relationship must be collection.
  • All relationship object sets at least have an ID value
Tip
  • When no node IDs are found on shadingEngines please save your scene and try again.
Source code in client/ayon_maya/plugins/publish/validate_look_contents.py
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
class ValidateLookContentsFiles(plugin.MayaInstancePlugin):
    """Validate look resources have valid files.

    Rules:
        * Look data must have `relationships` and `attributes` keys.
        * At least one relationship must be collection.
        * All relationship object sets at least have an ID value

    Tip:
        * When no node IDs are found on shadingEngines please save your scene
        and try again.

    """

    order = ValidateContentsOrder
    families = ['look']
    label = 'Textures Have No Files'
    actions = [ayon_maya.api.action.SelectInvalidAction]

    def process(self, instance: pyblish.api.Instance):
        if self.get_invalid(instance):
            raise PublishValidationError(
                "Look has file nodes for which no files were found on disk.",
                description=self.get_description())

    @classmethod
    def get_invalid(cls, instance: pyblish.api.Instance) -> List[str]:
        """Get all invalid nodes"""
        invalid = []
        resources = instance.data.get("resources", [])
        for resource in resources:
            files = resource["files"]
            if len(files) == 0:
                node = resource["node"]
                cls.log.error("File node '%s' uses no or non-existing "
                              "files" % node)
                invalid.append(node)
        return invalid

    @staticmethod
    def get_description() -> str:
        return inspect.cleandoc("""
            ### Look texture has no files

            Missing files on disk for textures used by the look. This may be
            because the texture has no filepath set or points to a non-existing
            path.

            Files used by the textures and file nodes must exist on disk. 
            Please update the relevant filepaths.                    
        """)

get_invalid(instance) classmethod

Get all invalid nodes

Source code in client/ayon_maya/plugins/publish/validate_look_contents.py
183
184
185
186
187
188
189
190
191
192
193
194
195
@classmethod
def get_invalid(cls, instance: pyblish.api.Instance) -> List[str]:
    """Get all invalid nodes"""
    invalid = []
    resources = instance.data.get("resources", [])
    for resource in resources:
        files = resource["files"]
        if len(files) == 0:
            node = resource["node"]
            cls.log.error("File node '%s' uses no or non-existing "
                          "files" % node)
            invalid.append(node)
    return invalid