init
This commit is contained in:
commit
e8a255ce1f
10 changed files with 1390 additions and 0 deletions
141
generate/generate.js
Normal file
141
generate/generate.js
Normal file
|
@ -0,0 +1,141 @@
|
|||
/**
|
||||
* Generates a sprite sheet and emoji JSON file for use by the plugin.
|
||||
* Takes one argument, the root directory of your emoji files.
|
||||
* This makes a few assumptions:
|
||||
* - All emojis are PNG files.
|
||||
* - All emojis are the same size.
|
||||
* - All emojis are static.
|
||||
* - No filenames have spaces.
|
||||
*/
|
||||
|
||||
import { exec as nodeExec } from "node:child_process";
|
||||
import { argv } from "node:process";
|
||||
import { promisify } from "node:util";
|
||||
import * as fs from "node:fs";
|
||||
import { join as joinPath } from "node:path";
|
||||
|
||||
const writeFile = promisify(fs.writeFile);
|
||||
const readDir = promisify(fs.readdir);
|
||||
const exec = promisify(nodeExec);
|
||||
|
||||
let directory = ".";
|
||||
let outname = "spritesheet";
|
||||
let scale = 0;
|
||||
if (argv.length < 2) {
|
||||
throw "Not enough arguments, need a folder to process";
|
||||
}
|
||||
|
||||
if (argv[0].indexOf("node") !== -1 && argv[1].indexOf("generate.js") !== -1) {
|
||||
if (argv.length < 3) throw "Not enough arguments, need a folder to process";
|
||||
directory = argv[2];
|
||||
if (argv.length > 3) outname = argv[3];
|
||||
if (argv.length > 4) scale = parseInt(argv[4]);
|
||||
} else {
|
||||
directory = argv[1];
|
||||
if (argv.length > 2) outname = argv[2];
|
||||
if (argv.length > 3) scale = parseInt(argv[3]);
|
||||
}
|
||||
|
||||
async function getFiles() {
|
||||
return (await readDir(directory))
|
||||
.filter((f) => f.endsWith(".png"))
|
||||
.sort((a, b) => a.localeCompare(b));
|
||||
}
|
||||
|
||||
console.log(`Directory: ${directory}
|
||||
Output files: ${outname}.png, ${outname}.json
|
||||
Scale: ${scale}`);
|
||||
|
||||
const files = await getFiles();
|
||||
const { size } = await createSpriteSheet(files);
|
||||
await createJSON(files, size);
|
||||
|
||||
/**
|
||||
* @param {string[]} files
|
||||
*/
|
||||
async function createSpriteSheet(files) {
|
||||
const size = Math.ceil(Math.sqrt(files.length));
|
||||
|
||||
// i don't wanna pull in any more dependencies, so lol
|
||||
if (!scale) {
|
||||
const { stdout: rawImageSize } = await exec(
|
||||
[
|
||||
"magick",
|
||||
"identify",
|
||||
"-ping",
|
||||
"-format",
|
||||
"'%w'",
|
||||
joinPath(directory, files[0]),
|
||||
].join(" ")
|
||||
);
|
||||
scale = parseInt(rawImageSize);
|
||||
}
|
||||
|
||||
const { stdout, stderr } = await exec(
|
||||
[
|
||||
"magick",
|
||||
"montage",
|
||||
"-tile",
|
||||
`${size}x${size}`,
|
||||
"-geometry",
|
||||
"+0+0",
|
||||
"-scale",
|
||||
`${scale}`,
|
||||
"-background",
|
||||
"transparent",
|
||||
...files.map((f) => joinPath(directory, f)),
|
||||
`${outname}.png`,
|
||||
].join(" ")
|
||||
);
|
||||
if (stderr) {
|
||||
console.error("Error from ImageMagick:", stderr);
|
||||
return;
|
||||
}
|
||||
if (stdout) console.log(stdout);
|
||||
|
||||
const { stdout2, stderr2 } = await exec(
|
||||
[
|
||||
"magick",
|
||||
"montage",
|
||||
"-tile",
|
||||
`${size}x${size}`,
|
||||
"-geometry",
|
||||
"+0+0",
|
||||
"-scale",
|
||||
`${scale * 2}`,
|
||||
"-background",
|
||||
"transparent",
|
||||
...files.map((f) => joinPath(directory, f)),
|
||||
`${outname}_2x.png`,
|
||||
].join(" ")
|
||||
);
|
||||
if (stderr2) {
|
||||
console.error("Error from ImageMagick:", stderr2);
|
||||
return;
|
||||
}
|
||||
if (stdout2) console.log(stdout2);
|
||||
|
||||
return { size };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} files The image filenames.
|
||||
* @param {number} size The size of the sprite sheet in number of sprites horizontally and vertically.
|
||||
*/
|
||||
async function createJSON(files, size) {
|
||||
let json = {
|
||||
source: `${outname}.png`,
|
||||
hidpiSource: `${outname}_2x.png`,
|
||||
size: scale,
|
||||
emojis: {},
|
||||
};
|
||||
|
||||
files.forEach((filename, index) => {
|
||||
const shortcode = filename.split(".", 2)[0];
|
||||
const xPos = Math.floor(index % size);
|
||||
const yPos = Math.floor(index / size);
|
||||
json.emojis[shortcode] = [xPos * scale, yPos * scale];
|
||||
});
|
||||
|
||||
await writeFile(`${outname}.json`, JSON.stringify(json, undefined, " "));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue