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();
 |