@bscotch/sprite-source
Version:
Art pipeline scripting module for GameMaker sprites.
101 lines • 3.09 kB
JavaScript
import { pathy, rmSafe } from '@bscotch/pathy';
import fsp from 'fs/promises';
import path from 'path';
import { readdirSafe, readdirSafeWithFileTypes } from './safeFs.js';
export function check(func, message) {
const handleError = (err) => {
const error = new Error(message);
error.cause = err;
return [error, null];
};
try {
const result = func();
// Handle async functions
if (result instanceof Promise) {
return result.then((result) => [null, result], (cause) => handleError(cause));
}
return [null, result];
}
catch (cause) {
return handleError(cause);
}
}
export class SpriteSourceError extends Error {
constructor(message, cause, asserter) {
super(message);
this.name = 'SpriteSourceError';
this.cause = cause;
Error.captureStackTrace(this, asserter || this.constructor);
}
}
export function assert(condition, message, cause) {
if (!condition) {
const err = new SpriteSourceError(message, cause, assert);
throw err;
}
}
export function rethrow(cause, message) {
const error = new Error(message);
error.cause = cause;
throw error;
}
export async function getDirs(rootFolder, maxDepth = Infinity) {
const spriteDirs = [];
async function walk(dir, depth = 1) {
if (depth > maxDepth)
return;
const files = await readdirSafeWithFileTypes(dir);
await Promise.all(files.map(async (file) => {
const filePath = path.join(dir, file.name);
if (file.isDirectory()) {
// Add as a Pathy instance where the cwd is the root folder
spriteDirs.push(pathy(filePath, rootFolder));
await walk(filePath, depth + 1);
}
}));
}
await walk(rootFolder);
return spriteDirs;
}
/**
* Delete the PNG images inside a folder. Returns the list of
* deleted images.
*/
export async function deletePngChildren(path) {
if (!(await path.exists())) {
return [];
}
const files = await readdirSafe(path.absolute);
const deleteWaits = [];
const deleted = [];
for (const file of files) {
if (file.match(/\.png$/i)) {
const toDelete = path.join(file);
deleted.push(toDelete);
deleteWaits.push(rmSafe(toDelete.absolute));
}
}
await Promise.all(deleteWaits);
return deleted;
}
/**
* Asynchronously get the size of a PNG image, given its path,
* with maximal speed.
*/
export async function getPngSize(path) {
const size = { width: 0, height: 0 };
const fd = await fsp.open(path.absolute, 'r');
try {
const buf = Buffer.alloc(24);
await fd.read(buf, 0, 24, 16);
size.width = buf.readUInt32BE(0);
size.height = buf.readUInt32BE(4);
}
finally {
await fd.close();
}
assert(size.width > 0, `Invalid width for ${path}`);
assert(size.height > 0, `Invalid height for ${path}`);
return size;
}
//# sourceMappingURL=utility.js.map