| 160 | */ |
| 161 | |
| 162 | export const toktx = function (options: ETC1SOptions | UASTCOptions): Transform { |
| 163 | options = { |
| 164 | ...(options.mode === Mode.ETC1S ? ETC1S_DEFAULTS : UASTC_DEFAULTS), |
| 165 | ...options, |
| 166 | }; |
| 167 | |
| 168 | return createTransform(options.mode, async (doc: Document): Promise<void> => { |
| 169 | const logger = doc.getLogger(); |
| 170 | |
| 171 | // Confirm recent version of KTX-Software is installed. |
| 172 | await checkKTXSoftware(logger); |
| 173 | |
| 174 | // Create workspace. Avoid 'unsafeCleanup' and 'setGracefulCleanup', which |
| 175 | // are not working as expected and are slated for removal: |
| 176 | // https://github.com/raszi/node-tmp/pull/281 |
| 177 | const batchPrefix = uuid(); |
| 178 | const batchDir = tmp.dirSync({ prefix: 'gltf-transform-' }); |
| 179 | |
| 180 | const basisuExtension = doc.createExtension(KHRTextureBasisu).setRequired(true); |
| 181 | |
| 182 | const textures = doc.getRoot().listTextures(); |
| 183 | const numTextures = textures.length; |
| 184 | |
| 185 | await pLimit(textures, options.jobs!, async (texture, textureIndex) => { |
| 186 | const slots = listTextureSlots(texture); |
| 187 | const channels = getTextureChannelMask(texture); |
| 188 | const textureLabel = |
| 189 | texture.getURI() || texture.getName() || `${textureIndex + 1}/${doc.getRoot().listTextures().length}`; |
| 190 | const prefix = `ktx:texture(${textureLabel})`; |
| 191 | logger.debug(`${prefix}: Slots → [${slots.join(', ')}]`); |
| 192 | |
| 193 | // FILTER: Exclude textures that don't match (a) 'slots' or (b) expected formats. |
| 194 | |
| 195 | if (typeof options.slots === 'string') { |
| 196 | options.slots = micromatch.makeRe(options.slots, MICROMATCH_OPTIONS); |
| 197 | logger.warn('ktx: Argument "slots" should be of type `RegExp | null`.'); |
| 198 | } |
| 199 | |
| 200 | const patternRe = options.pattern as RegExp | null; |
| 201 | const slotsRe = options.slots as RegExp | null; |
| 202 | |
| 203 | let srcMimeType = texture.getMimeType(); |
| 204 | |
| 205 | if (srcMimeType === 'image/ktx2') { |
| 206 | logger.debug(`${prefix}: Skipping, already KTX.`); |
| 207 | return; |
| 208 | } else if (srcMimeType !== 'image/png' && srcMimeType !== 'image/jpeg') { |
| 209 | logger.warn(`${prefix}: Skipping, unsupported texture type "${texture.getMimeType()}".`); |
| 210 | return; |
| 211 | } else if (slotsRe && !slots.find((slot) => slot.match(slotsRe))) { |
| 212 | logger.debug(`${prefix}: Skipping, [${slots.join(', ')}] excluded by "slots" parameter.`); |
| 213 | return; |
| 214 | } else if (patternRe && !(texture.getURI().match(patternRe) || texture.getName().match(patternRe))) { |
| 215 | logger.debug(`${prefix}: Skipping, excluded by "pattern" parameter.`); |
| 216 | return; |
| 217 | } |
| 218 | |
| 219 | let srcImage = texture.getImage()!; |