mirror of
				https://github.com/tobspr/shapez.io.git
				synced 2025-06-13 13:04:03 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			213 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/**
 | 
						|
 *
 | 
						|
 * Run `yarn global add canvas` first
 | 
						|
 */
 | 
						|
 | 
						|
const { createCanvas } = require("canvas");
 | 
						|
const fs = require("fs");
 | 
						|
const path = require("path");
 | 
						|
 | 
						|
const outputFolder = path.join(__dirname, "..", "wires", "sets");
 | 
						|
 | 
						|
const dimensions = 192;
 | 
						|
const lineSize = 14;
 | 
						|
const lowerLineSize = 32;
 | 
						|
 | 
						|
const variants = {
 | 
						|
    first: "#61ef6f",
 | 
						|
    second: "#5fb2f1",
 | 
						|
    conflict: "#f74c4c",
 | 
						|
};
 | 
						|
 | 
						|
function hexToRGB(h) {
 | 
						|
    let r = 0,
 | 
						|
        g = 0,
 | 
						|
        b = 0;
 | 
						|
 | 
						|
    // 3 digits
 | 
						|
    if (h.length == 4) {
 | 
						|
        r = "0x" + h[1] + h[1];
 | 
						|
        g = "0x" + h[2] + h[2];
 | 
						|
        b = "0x" + h[3] + h[3];
 | 
						|
 | 
						|
        // 6 digits
 | 
						|
    } else if (h.length == 7) {
 | 
						|
        r = "0x" + h[1] + h[2];
 | 
						|
        g = "0x" + h[3] + h[4];
 | 
						|
        b = "0x" + h[5] + h[6];
 | 
						|
    }
 | 
						|
 | 
						|
    return [+r, +g, +b];
 | 
						|
}
 | 
						|
 | 
						|
function RGBToHSL(r, g, b) {
 | 
						|
    // Make r, g, and b fractions of 1
 | 
						|
    r /= 255;
 | 
						|
    g /= 255;
 | 
						|
    b /= 255;
 | 
						|
 | 
						|
    // Find greatest and smallest channel values
 | 
						|
    let cmin = Math.min(r, g, b),
 | 
						|
        cmax = Math.max(r, g, b),
 | 
						|
        delta = cmax - cmin,
 | 
						|
        h = 0,
 | 
						|
        s = 0,
 | 
						|
        l = 0;
 | 
						|
    // Calculate hue
 | 
						|
    // No difference
 | 
						|
    if (delta == 0) h = 0;
 | 
						|
    // Red is max
 | 
						|
    else if (cmax == r) h = ((g - b) / delta) % 6;
 | 
						|
    // Green is max
 | 
						|
    else if (cmax == g) h = (b - r) / delta + 2;
 | 
						|
    // Blue is max
 | 
						|
    else h = (r - g) / delta + 4;
 | 
						|
 | 
						|
    h = Math.round(h * 60);
 | 
						|
 | 
						|
    // Make negative hues positive behind 360°
 | 
						|
    if (h < 0) h += 360;
 | 
						|
 | 
						|
    // Calculate lightness
 | 
						|
    l = (cmax + cmin) / 2;
 | 
						|
 | 
						|
    // Calculate saturation
 | 
						|
    s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
 | 
						|
 | 
						|
    // Multiply l and s by 100
 | 
						|
    s = +(s * 100).toFixed(1);
 | 
						|
    l = +(l * 100).toFixed(1);
 | 
						|
 | 
						|
    return [h, s, l];
 | 
						|
}
 | 
						|
 | 
						|
function HSLToRGB(h, s, l) {
 | 
						|
    // Must be fractions of 1
 | 
						|
    s /= 100;
 | 
						|
    l /= 100;
 | 
						|
 | 
						|
    let c = (1 - Math.abs(2 * l - 1)) * s,
 | 
						|
        x = c * (1 - Math.abs(((h / 60) % 2) - 1)),
 | 
						|
        m = l - c / 2,
 | 
						|
        r = 0,
 | 
						|
        g = 0,
 | 
						|
        b = 0;
 | 
						|
 | 
						|
    if (0 <= h && h < 60) {
 | 
						|
        r = c;
 | 
						|
        g = x;
 | 
						|
        b = 0;
 | 
						|
    } else if (60 <= h && h < 120) {
 | 
						|
        r = x;
 | 
						|
        g = c;
 | 
						|
        b = 0;
 | 
						|
    } else if (120 <= h && h < 180) {
 | 
						|
        r = 0;
 | 
						|
        g = c;
 | 
						|
        b = x;
 | 
						|
    } else if (180 <= h && h < 240) {
 | 
						|
        r = 0;
 | 
						|
        g = x;
 | 
						|
        b = c;
 | 
						|
    } else if (240 <= h && h < 300) {
 | 
						|
        r = x;
 | 
						|
        g = 0;
 | 
						|
        b = c;
 | 
						|
    } else if (300 <= h && h < 360) {
 | 
						|
        r = c;
 | 
						|
        g = 0;
 | 
						|
        b = x;
 | 
						|
    }
 | 
						|
    r = Math.round((r + m) * 255);
 | 
						|
    g = Math.round((g + m) * 255);
 | 
						|
    b = Math.round((b + m) * 255);
 | 
						|
 | 
						|
    return [r, g, b];
 | 
						|
}
 | 
						|
 | 
						|
async function run() {
 | 
						|
    console.log("Running");
 | 
						|
 | 
						|
    const promises = [];
 | 
						|
 | 
						|
    for (const variantId in variants) {
 | 
						|
        const variantColor = variants[variantId];
 | 
						|
        const variantHSL = RGBToHSL(...hexToRGB(variantColor));
 | 
						|
        const darkenedColor = HSLToRGB(variantHSL[0], variantHSL[1] - 15, variantHSL[2] - 20);
 | 
						|
        const hexDarkenedColor = "rgb(" + darkenedColor.join(",") + ")";
 | 
						|
 | 
						|
        console.log(variantColor, "->", hexToRGB(variantColor), variantHSL, "->", darkenedColor);
 | 
						|
 | 
						|
        const parts = {
 | 
						|
            forward: [[0.5, 0, 0.5, 1]],
 | 
						|
            turn: [
 | 
						|
                [0.5, 0.5, 0.5, 1],
 | 
						|
                [0.5, 0.5, 1, 0.5],
 | 
						|
            ],
 | 
						|
            split: [
 | 
						|
                [0.5, 0.5, 0.5, 1],
 | 
						|
                [0, 0.5, 1, 0.5],
 | 
						|
            ],
 | 
						|
            cross: [
 | 
						|
                [0, 0.5, 1, 0.5],
 | 
						|
                [0.5, 0, 0.5, 1],
 | 
						|
            ],
 | 
						|
        };
 | 
						|
 | 
						|
        for (const partId in parts) {
 | 
						|
            const partLines = parts[partId];
 | 
						|
 | 
						|
            const canvas = createCanvas(dimensions, dimensions);
 | 
						|
            const context = canvas.getContext("2d");
 | 
						|
            context.quality = "best";
 | 
						|
            context.clearRect(0, 0, dimensions, dimensions);
 | 
						|
 | 
						|
            const lineCanvas = createCanvas(dimensions, dimensions);
 | 
						|
            const lineContext = lineCanvas.getContext("2d");
 | 
						|
            lineContext.quality = "best";
 | 
						|
            lineContext.clearRect(0, 0, dimensions, dimensions);
 | 
						|
            lineContext.strokeStyle = hexDarkenedColor;
 | 
						|
            lineContext.lineWidth = lowerLineSize;
 | 
						|
            lineContext.lineCap = "square";
 | 
						|
            lineContext.imageSmoothingEnabled = false;
 | 
						|
 | 
						|
            // Draw lower lines
 | 
						|
            partLines.forEach(([x1, y1, x2, y2]) => {
 | 
						|
                lineContext.beginPath();
 | 
						|
                lineContext.moveTo(x1 * dimensions, y1 * dimensions);
 | 
						|
                lineContext.lineTo(x2 * dimensions, y2 * dimensions);
 | 
						|
                lineContext.stroke();
 | 
						|
            });
 | 
						|
 | 
						|
            context.globalAlpha = 0.4;
 | 
						|
            context.drawImage(lineCanvas, 0, 0, dimensions, dimensions);
 | 
						|
 | 
						|
            context.globalAlpha = 1;
 | 
						|
            context.imageSmoothingEnabled = false;
 | 
						|
            context.lineCap = "square";
 | 
						|
            context.strokeStyle = variantColor;
 | 
						|
            context.lineWidth = lineSize;
 | 
						|
 | 
						|
            // Draw upper lines
 | 
						|
            partLines.forEach(([x1, y1, x2, y2]) => {
 | 
						|
                context.beginPath();
 | 
						|
                context.moveTo(x1 * dimensions, y1 * dimensions);
 | 
						|
                context.lineTo(x2 * dimensions, y2 * dimensions);
 | 
						|
                context.stroke();
 | 
						|
            });
 | 
						|
 | 
						|
            const out = fs.createWriteStream(path.join(outputFolder, variantId + "_" + partId + ".png"));
 | 
						|
            const stream = canvas.createPNGStream();
 | 
						|
            stream.pipe(out);
 | 
						|
            promises.push(new Promise(resolve => stream.on("end", resolve)));
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    console.log("Waiting for completion");
 | 
						|
    await Promise.all(promises);
 | 
						|
 | 
						|
    console.log("Done!");
 | 
						|
}
 | 
						|
 | 
						|
run();
 |