Skip to content

collect_texture_instance

CollectTextureInstance

Bases: InstancePlugin

Collect texture instance representations as UDIMs.

Source code in client/ayon_traypublisher/plugins/publish/collect_texture_instance.py
  8
  9
 10
 11
 12
 13
 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
class CollectTextureInstance(pyblish.api.InstancePlugin):
    """Collect texture instance representations as UDIMs."""

    label = "Collect Texture Instance"
    order = pyblish.api.CollectorOrder - 0.48
    families = ["texture_creator"]
    hosts = ["traypublisher"]

    def process(self, instance: pyblish.api.Instance):
        creator_attributes = instance.data["creator_attributes"]
        filepath_items = creator_attributes["representation_files"]
        if not isinstance(filepath_items, list):
            filepath_items = [filepath_items]

        representations = instance.data.setdefault("representations", [])
        is_udim: bool = creator_attributes.get("is_udim", True)
        for filepath_item in filepath_items:
            representation = self._create_representation_data(
                filepath_item,
                assume_sequence_as_udim=is_udim)
            if representation:
                representations.append(representation)

    def _create_representation_data(
        self, filepath_item, assume_sequence_as_udim
    ):
        """Create new representation data based on file item.

        This method processes the provided file item to generate a dictionary
        containing representation data. If the file item represents a UDIM
        texture sequence, the method collects UDIM frame indexes and attaches
        them to the representation data under the `udim` key.

        Args:
            filepath_item (dict[str, Any]): Item with information about
                representation paths.
            assume_sequence_as_udim (bool): Whether an input file sequence
                should be considered as UDIM sequence instead of animated
                frame range sequence.

        Returns:
            dict[str, Any]: Prepared base representation data, including
            fields such as `ext`, `name`, `stagingDir`, `files`, `tags`, and
            optionally `udim` if UDIMs are detected.
        """

        filenames = filepath_item["filenames"]
        if not filenames:
            return {}

        ext = os.path.splitext(filenames[0])[1].lstrip(".")
        if len(filenames) == 1:
            filenames = filenames[0]

        representation_data = {
            "ext": ext,
            "name": ext,
            "stagingDir": filepath_item["directory"],
            "files": filenames,
            "tags": []
        }

        if assume_sequence_as_udim:
            udims = self.collect_udims(representation_data)
            if udims:
                self.log.debug(f"Collected UDIMs: {udims}")
                representation_data["udim"] = udims

        return representation_data

    def collect_udims(self, representation: dict) -> list[str]:
        """Collect UDIMs from representation."""
        filenames = representation["files"]
        if not filenames or not isinstance(filenames, list):
            return []
        filenames: list[str]

        # clique.PATTERNS["frames"] but also allow `_` before digits
        # and enforce only detecting 4 digits
        pattern = r"[._](?P<index>(?P<padding>0*)\d+)\.\D+\d?$"
        collections, remainder = clique.assemble(
            filenames,
            minimum_items=1,
            patterns=[pattern],
        )
        if not collections:
            # Not a sequence filename
            self.log.debug(f"No UDIM sequence detected for {remainder}")
            return []

        if len(collections) != 1:
            raise ValueError(
                "Expected exactly one collection, "
                f"but found {collections}."
            )

        return [
            f"{frame:04d}" for frame in collections[0].indexes
        ]

collect_udims(representation)

Collect UDIMs from representation.

Source code in client/ayon_traypublisher/plugins/publish/collect_texture_instance.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
105
106
def collect_udims(self, representation: dict) -> list[str]:
    """Collect UDIMs from representation."""
    filenames = representation["files"]
    if not filenames or not isinstance(filenames, list):
        return []
    filenames: list[str]

    # clique.PATTERNS["frames"] but also allow `_` before digits
    # and enforce only detecting 4 digits
    pattern = r"[._](?P<index>(?P<padding>0*)\d+)\.\D+\d?$"
    collections, remainder = clique.assemble(
        filenames,
        minimum_items=1,
        patterns=[pattern],
    )
    if not collections:
        # Not a sequence filename
        self.log.debug(f"No UDIM sequence detected for {remainder}")
        return []

    if len(collections) != 1:
        raise ValueError(
            "Expected exactly one collection, "
            f"but found {collections}."
        )

    return [
        f"{frame:04d}" for frame in collections[0].indexes
    ]