From 980f09471aace79dbe6785c800a799d68aae2c54 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sat, 22 Feb 2025 13:00:04 +0700 Subject: [PATCH] New texture recolor script --- color datagen/base_with_mask.js | 68 +++++++++++++++++++++++++++++ color datagen/computer_block.sh | 4 ++ color datagen/include.js | 76 +++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 color datagen/base_with_mask.js create mode 100644 color datagen/computer_block.sh create mode 100644 color datagen/include.js diff --git a/color datagen/base_with_mask.js b/color datagen/base_with_mask.js new file mode 100644 index 000000000..e3be0dc5b --- /dev/null +++ b/color datagen/base_with_mask.js @@ -0,0 +1,68 @@ + +const args = process.argv.slice(2) + +if (args.length < 2) { + console.error('Usage: node base_with_mask.js [subfolder]\n') + console.error('If subfolder specified, resulting file name will contain only color name\n') + console.error('Subfolder is relative to base texture path\n') + process.exit(2) +} + +const fs = require('fs') +const {colorsWithWhite, rootFolder, splitName, getSize} = require('./include.js') +const child_process = require('child_process'); + +(async function() { + const baseTexture = args[0] + const maskTexture = args[1] + const subfolder = args[2] ?? '' + + const fBase = `${rootFolder}${baseTexture}.png` + const fMask = `${rootFolder}${maskTexture}.png` + + if (!fs.existsSync(fBase)) { + process.stderr.write(`${fBase} does not exist\n`) + process.exit(1) + } + + if (!fs.existsSync(fMask)) { + process.stderr.write(`${fMask} does not exist\n`) + process.exit(1) + } + + const [fileName, _, fullBaseFolder] = splitName(baseTexture) + const bSize = (await getSize(fBase))[2] + const mSize = (await getSize(fMask))[2] + + if (bSize != mSize) { + process.stderr.write(`${fBase} has size of ${bSize}, ${fMask} has size of ${mSize}!\n`) + process.exit(3) + } + + for (const [name, _, xc] of colorsWithWhite) { + const outputFilename = subfolder === '' ? `${fullBaseFolder}/${fileName}_${name}.png` : `${fullBaseFolder}/${subfolder}/${name}.png` + + const magick = child_process.spawn('magick', [ + 'convert', + + fBase, + + '(', + fMask, + '-size', bSize, + xc, + '-channel', 'rgb', + '-compose', 'Multiply', + '-composite', + ')', + + '-compose', 'Over', + '-composite', + + outputFilename]) + + magick.stdout.pipe(process.stdout) + magick.stderr.pipe(process.stderr) + } +})(); + diff --git a/color datagen/computer_block.sh b/color datagen/computer_block.sh new file mode 100644 index 000000000..0c01736c0 --- /dev/null +++ b/color datagen/computer_block.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +node ./base_with_mask.js block/decorative/computer_base block/decorative/computer_base_mask computer_base +node ./base_with_mask.js block/decorative/computer_screen block/decorative/computer_screen_mask computer_screen diff --git a/color datagen/include.js b/color datagen/include.js new file mode 100644 index 000000000..8d2f3b625 --- /dev/null +++ b/color datagen/include.js @@ -0,0 +1,76 @@ + +const colors = [ + ['orange', [245, 116, 16]], + ['magenta', [186, 63, 175]], + ['light_blue', [59, 180, 219]], + ['yellow', [252, 199, 36]], + ['lime', [111, 187, 24]], + ['pink', [243, 139, 170]], + ['gray', [62, 66, 70]], + ['light_gray', [140, 140, 131]], + ['cyan', [22, 134, 145]], + ['purple', [116, 38, 169]], + ['blue', [51, 53, 155]], + ['brown', [114, 71, 40]], + ['green', [84, 109, 28]], + ['red', [156, 37, 34]], + ['black', [31, 31, 35]], +] + +const white = ['white', [235, 235, 235]] +const colorsWithWhite = [...colors] +colorsWithWhite.push(white) + +function addRgbString(values) { + for (const row of values) { + const rgb = row[1] + row.push(`xc:rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`) + } +} + +addRgbString(colors) +addRgbString(colorsWithWhite) + +const rootFolder = '../src/main/resources/assets/overdrive_that_matters/textures/' +const child_process = require('child_process') + +process.stdout.setMaxListeners(900) +process.stderr.setMaxListeners(900) + +async function getSize(path) { + const identify = child_process.spawn('magick', [ + 'identify', + path, + ]) + + identify.stderr.pipe(process.stderr) + + const chunks = [] + identify.stdout.on('data', (a) => chunks.push(a)) + + await new Promise((resolve) => { + identify.on('close', () => resolve()) + }) + + const chunk = chunks[0].toString('utf-8') + const size = chunk.match(/PNG ([0-9]+)x([0-9]+)/) + const width = parseInt(size[1]) + const height = parseInt(size[2]) + + return [width, height, `${width}x${height}`] +} + +function splitName(name) { + const splitted = name.split('/') + const fileName = splitted.pop() + const baseFolder = splitted.join('/') + const fullBaseFolder = `${rootFolder}${baseFolder}` + + return [fileName, baseFolder, fullBaseFolder, fileName.indexOf('_white') == -1 ? colorsWithWhite : colors] +} + +exports.colors = colors +exports.colorsWithWhite = colorsWithWhite +exports.rootFolder = rootFolder +exports.splitName = splitName +exports.getSize = getSize