Skip to content

create_textures

Creator plugin for creating textures.

CreateTextures

Bases: Creator

Create a texture set.

Source code in client/ayon_substancepainter/plugins/create/create_textures.py
 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
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
class CreateTextures(Creator):
    """Create a texture set."""
    identifier = "io.openpype.creators.substancepainter.textureset"
    label = "Textures"
    product_type = "textureSet"
    icon = "picture-o"

    default_variant = "Main"
    settings_category = "substancepainter"
    channel_mapping = []

    def apply_settings(self, project_settings):
        settings = project_settings["substancepainter"].get("create", [])  # noqa
        if settings:
            self.channel_mapping = settings["CreateTextures"].get(
                "channel_mapping", [])


    def create(self, product_name, instance_data, pre_create_data):
        if not substance_painter.project.is_open():
            raise CreatorError("Can't create a Texture Set instance without "
                               "an open project.")
        # Transfer settings from pre create to instance
        creator_attributes = instance_data.setdefault(
            "creator_attributes", dict())
        for key in [
            "review",
            "exportPresetUrl",
            "exportFileFormat",
            "exportSize",
            "exportPadding",
            "exportDilationDistance",
            "useCustomExportPreset",
            "exportChannel",
            "exportTextureSets",
            "flattenTextureSets"
        ]:
            if key in pre_create_data:
                creator_attributes[key] = pre_create_data[key]

        if pre_create_data.get("use_selection"):
            stack = substance_painter.textureset.get_active_stack()

            instance_data["selected_node_id"] = [
                node_number.uid() for node_number in
                substance_painter.layerstack.get_selected_nodes(stack)]

        instance = self.create_instance_in_context(product_name,
                                                   instance_data)
        set_instance(
            instance_id=instance["instance_id"],
            instance_data=instance.data_to_store()
        )

    def collect_instances(self):
        for instance in get_instances():
            if (instance.get("creator_identifier") == self.identifier or
                    instance.get("productType") == self.product_type):
                self.create_instance_in_context_from_existing(instance)

    def update_instances(self, update_list):
        instance_data_by_id = {}
        for instance, _changes in update_list:
            # Persist the data
            instance_id = instance.get("instance_id")
            instance_data = instance.data_to_store()
            instance_data_by_id[instance_id] = instance_data
        set_instances(instance_data_by_id, update=True)

    def remove_instances(self, instances):
        for instance in instances:
            remove_instance(instance["instance_id"])
            self._remove_instance_from_context(instance)

    # Helper methods (this might get moved into Creator class)
    def create_instance_in_context(self, product_name, data):
        instance = CreatedInstance(
            self.product_type, product_name, data, self
        )
        self.create_context.creator_adds_instance(instance)
        return instance

    def create_instance_in_context_from_existing(self, data):
        instance = CreatedInstance.from_existing(data, self)
        self.create_context.creator_adds_instance(instance)
        return instance

    def get_instance_attr_defs(self):
        if self.channel_mapping:
            export_channel_enum = {
                item["value"]: item["name"]
                for item in self.channel_mapping
            }
        else:
            export_channel_enum = {
                "BaseColor": "Base Color",
                "Metallic": "Metallic",
                "Roughness": "Roughness",
                "SpecularEdgeColor": "Specular Edge Color",
                "Emissive": "Emissive",
                "Opacity": "Opacity",
                "Displacement": "Displacement",
                "Glossiness": "Glossiness",
                "Anisotropylevel": "Anisotropy Level",
                "AO": "Ambient Occulsion",
                "Anisotropyangle": "Anisotropy Angle",
                "Transmissive": "Transmissive",
                "Reflection": "Reflection",
                "Diffuse": "Diffuse",
                "Ior": "Index of Refraction",
                "Specularlevel": "Specular Level",
                "BlendingMask": "Blending Mask",
                "Translucency": "Translucency",
                "Scattering": "Scattering",
                "ScatterColor": "Scatter Color",
                "SheenOpacity": "Sheen Opacity",
                "SheenRoughness": "Sheen Roughness",
                "SheenColor": "Sheen Color",
                "CoatOpacity": "Coat Opacity",
                "CoatColor": "Coat Color",
                "CoatRoughness": "Coat Roughness",
                "CoatSpecularLevel": "Coat Specular Level",
                "CoatNormal": "Coat Normal",
            }
        export_texture_set_enum = {
            texture_set.name(): texture_set.name()
            for texture_set in substance_painter.textureset.all_texture_sets()
        }

        return [
            BoolDef("review",
                    label="Review",
                    tooltip="Mark as reviewable",
                    default=True),
            BoolDef("flattenTextureSets",
                    label="Flatten Texture Sets As One Texture Output",
                    tooltip="Export multiple texture set(s) "
                            "as one Texture Output",
                    default=False),
            EnumDef("exportTextureSets",
                    items=export_texture_set_enum,
                    multiselection=True,
                    default=None,
                    label="Export Texture Set(s)",
                    tooltip="Choose the texture set(s) which "
                            "you want to export. If no sets are "
                            "are selected then all texture sets "
                            "will be exported."),
            EnumDef("exportChannel",
                    items=export_channel_enum,
                    multiselection=True,
                    default=None,
                    label="Export Channel(s)",
                    tooltip="Choose the channel which you "
                            "want to solely export. The value "
                            "is 'None' by default which exports "
                            "all channels"),
            EnumDef("exportPresetUrl",
                    items=get_export_presets(),
                    label="Output Template"),
            BoolDef("allowSkippedMaps",
                    label="Allow Skipped Output Maps",
                    tooltip="When enabled this allows the publish to ignore "
                            "output maps in the used output template if one "
                            "or more maps are skipped due to the required "
                            "channels not being present in the current file.",
                    default=True),
            EnumDef("exportFileFormat",
                    items={
                        None: "Based on output template",
                        # TODO: Get available extensions from substance API
                        "bmp": "bmp",
                        "ico": "ico",
                        "jpeg": "jpeg",
                        "jng": "jng",
                        "pbm": "pbm",
                        "pgm": "pgm",
                        "png": "png",
                        "ppm": "ppm",
                        "tga": "targa",
                        "tif": "tiff",
                        "wap": "wap",
                        "wbmp": "wbmp",
                        "xpm": "xpm",
                        "gif": "gif",
                        "hdr": "hdr",
                        "exr": "exr",
                        "j2k": "j2k",
                        "jp2": "jp2",
                        "pfm": "pfm",
                        "webp": "webp",
                        # TODO: Unsure why jxr format fails to export
                        # "jxr": "jpeg-xr",
                        # TODO: File formats that combine the exported textures
                        #   like psd are not correctly supported due to
                        #   publishing only a single file
                        # "psd": "psd",
                        # "sbsar": "sbsar",
                    },
                    default=None,
                    label="File type"),
            EnumDef("exportSize",
                    items={
                        None: "Based on each Texture Set's size",
                        #  The key is size of the texture file in log2.
                        #  (i.e. 10 means 2^10 = 1024)
                        7: "128",
                        8: "256",
                        9: "512",
                        10: "1024",
                        11: "2048",
                        12: "4096",
                        13: "8192"
                    },
                    default=None,
                    label="Size"),
            EnumDef("exportPadding",
                    items={
                        "passthrough": "No padding (passthrough)",
                        "infinite": "Dilation infinite",
                        "transparent": "Dilation + transparent",
                        "color": "Dilation + default background color",
                        "diffusion": "Dilation + diffusion"
                    },
                    default="infinite",
                    label="Padding"),
            NumberDef("exportDilationDistance",
                      minimum=0,
                      maximum=256,
                      decimals=0,
                      default=16,
                      label="Dilation Distance"),
            UILabelDef("*only used with "
                       "'Dilation + <x>' padding"),
        ]

    def get_pre_create_attr_defs(self):
        # Use same attributes as for instance attributes
        attr_defs = []
        if  substance_painter.application.version_info()[0] >= 10:
            attr_defs.append(
                BoolDef("use_selection", label="Use selection",
                        tooltip="Select Layer Stack(s) for exporting")
            )
        return attr_defs + self.get_instance_attr_defs()