mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
Merge branch 'master' of github.com:tobspr/shapez.io
This commit is contained in:
commit
1642354f40
@ -4,124 +4,155 @@ const { readFileSync, readdirSync, writeFileSync } = require("fs");
|
||||
const suffixToScale = {
|
||||
lq: "0.25",
|
||||
mq: "0.5",
|
||||
hq: "0.75"
|
||||
hq: "0.75",
|
||||
};
|
||||
|
||||
function convert(srcDir) {
|
||||
const full = resolve(srcDir);
|
||||
const srcFiles = readdirSync(full)
|
||||
const fullPath = resolve(srcDir);
|
||||
const srcFiles = readdirSync(fullPath)
|
||||
.filter(n => n.endsWith(".atlas"))
|
||||
.map(n => join(full, n));
|
||||
.map(n => join(fullPath, n));
|
||||
|
||||
for (const atlas of srcFiles) {
|
||||
console.log(`Processing: ${atlas}`);
|
||||
|
||||
// Read all text, split it into line array
|
||||
// and filter all empty lines
|
||||
const lines = readFileSync(atlas, "utf-8")
|
||||
.split("\n")
|
||||
.filter(n => n.trim());
|
||||
// Sections for different atlas images are broken up via an extra line break
|
||||
const atlasSections = readFileSync(atlas, "utf-8")
|
||||
.trim()
|
||||
.split("\n\n");
|
||||
|
||||
// Get source image name
|
||||
const image = lines.shift();
|
||||
const srcMeta = {};
|
||||
|
||||
// Read all metadata (supports only one page)
|
||||
while (true) {
|
||||
const kv = lines.shift().split(":");
|
||||
if (kv.length != 2) {
|
||||
lines.unshift(kv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
srcMeta[kv[0]] = kv[1].trim();
|
||||
console.log("Found " + atlasSections.length + " sections!");
|
||||
// Perform the conversion for each section
|
||||
for (const section of atlasSections) {
|
||||
preformConversion(fullPath, section);
|
||||
}
|
||||
|
||||
const frames = {};
|
||||
let current = null;
|
||||
|
||||
lines.push("Dummy line to make it convert last frame");
|
||||
|
||||
for (const line of lines) {
|
||||
if (!line.startsWith(" ")) {
|
||||
// New frame, convert previous if it exists
|
||||
if (current != null) {
|
||||
let { name, rotate, xy, size, orig, offset, index } = current;
|
||||
|
||||
// Convert to arrays because Node.js doesn't
|
||||
// support latest JS features
|
||||
xy = xy.split(",").map(v => Number(v));
|
||||
size = size.split(",").map(v => Number(v));
|
||||
orig = orig.split(",").map(v => Number(v));
|
||||
offset = offset.split(",").map(v => Number(v));
|
||||
|
||||
// GDX TexturePacker removes index suffixes
|
||||
const indexSuff = index != -1 ? `_${index}` : "";
|
||||
const isTrimmed = size != orig;
|
||||
|
||||
frames[`${name}${indexSuff}.png`] = {
|
||||
// Bounds on atlas
|
||||
frame: {
|
||||
x: xy[0],
|
||||
y: xy[1],
|
||||
w: size[0],
|
||||
h: size[1]
|
||||
},
|
||||
|
||||
// Whether image was rotated
|
||||
rotated: rotate == "true",
|
||||
trimmed: isTrimmed,
|
||||
|
||||
// How is the image trimmed
|
||||
spriteSourceSize: {
|
||||
x: offset[0],
|
||||
y: (orig[1] - size[1]) - offset[1],
|
||||
w: size[0],
|
||||
h: size[1]
|
||||
},
|
||||
|
||||
sourceSize: {
|
||||
w: orig[0],
|
||||
h: orig[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Simple object that will hold other metadata
|
||||
current = {
|
||||
name: line
|
||||
};
|
||||
} else {
|
||||
// Read and set current image metadata
|
||||
const kv = line.split(":").map(v => v.trim());
|
||||
current[kv[0]] = isNaN(Number(kv[1])) ? kv[1] : Number(kv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
const atlasSize = srcMeta.size.split(",").map(v => Number(v));
|
||||
const atlasScale = suffixToScale[atlas.match(/_(\w+)\.atlas$/)[1]];
|
||||
|
||||
const result = JSON.stringify({
|
||||
frames,
|
||||
meta: {
|
||||
image,
|
||||
format: srcMeta.format,
|
||||
size: {
|
||||
w: atlasSize[0],
|
||||
h: atlasSize[1]
|
||||
},
|
||||
scale: atlasScale.toString()
|
||||
}
|
||||
});
|
||||
|
||||
writeFileSync(atlas.replace(".atlas", ".json"), result, {
|
||||
encoding: "utf-8"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main == module) {
|
||||
convert(process.argv[2]);
|
||||
function formatImageData(keywordArgs) {
|
||||
let { name, rotate, xy, size, orig, offset, index } = keywordArgs;
|
||||
|
||||
// Convert to arrays because Node.js doesn't
|
||||
// support latest JS features
|
||||
xy = xy.split(",").map(v => Number(v));
|
||||
size = size.split(",").map(v => Number(v));
|
||||
orig = orig.split(",").map(v => Number(v));
|
||||
offset = offset.split(",").map(v => Number(v));
|
||||
|
||||
// GDX TexturePacker removes index suffixes
|
||||
let imageName = index === -1 ? `${name}.png` : `${name}_${index}.png`;
|
||||
|
||||
|
||||
const frameInfo = {
|
||||
// Bounds on atlas
|
||||
frame: {
|
||||
x: xy[0],
|
||||
y: xy[1],
|
||||
w: size[0],
|
||||
h: size[1],
|
||||
},
|
||||
|
||||
// Whether image was rotated
|
||||
rotated: rotate === "true",
|
||||
|
||||
// If blank space was trimmed from the image
|
||||
trimmed: size !== orig,
|
||||
|
||||
// How is the image trimmed
|
||||
spriteSourceSize: {
|
||||
x: offset[0],
|
||||
y: (orig[1] - size[1]) - offset[1],
|
||||
w: size[0],
|
||||
h: size[1],
|
||||
},
|
||||
|
||||
// Original image size
|
||||
sourceSize: {
|
||||
w: orig[0],
|
||||
h: orig[1],
|
||||
},
|
||||
};
|
||||
|
||||
return [imageName, frameInfo];
|
||||
}
|
||||
|
||||
function preformConversion(pathPrefix, atlasData) {
|
||||
// Read all text, split it into line array
|
||||
// and filter all empty lines
|
||||
const lines = atlasData
|
||||
.split("\n")
|
||||
.filter(n => n.trim());
|
||||
|
||||
// Get source image name
|
||||
const image = lines.shift();
|
||||
const srcMeta = {};
|
||||
|
||||
// Read all metadata
|
||||
while (true) {
|
||||
const nextLine = lines.shift();
|
||||
|
||||
// If a line does not contain a colon, we have gone too far
|
||||
if (!nextLine.includes(":")) {
|
||||
lines.unshift(nextLine);
|
||||
break;
|
||||
}
|
||||
|
||||
// Append the parsed key value pair to our metadata map
|
||||
const [key, value] = nextLine.split(":");
|
||||
srcMeta[key] = value.trim();
|
||||
}
|
||||
|
||||
const frames = {};
|
||||
let current = null;
|
||||
|
||||
for (const line of lines) {
|
||||
if (!line.startsWith(" ")) {
|
||||
// New frame, convert previous if it exists
|
||||
if (current !== null) {
|
||||
// Add the previous image's frame info to the frame map
|
||||
const [imageName, frameInfo] = formatImageData(current);
|
||||
frames[imageName] = frameInfo;
|
||||
}
|
||||
|
||||
// Reset the frame info with the new frame name.
|
||||
current = { name: line };
|
||||
} else {
|
||||
// Read and set current image metadata
|
||||
const [key, value] = line.split(":").map(v => v.trim());
|
||||
|
||||
// Check if the value should be a number
|
||||
const valueAsNum = Number(value);
|
||||
current[key] = isNaN(valueAsNum) ? value : valueAsNum;
|
||||
}
|
||||
}
|
||||
|
||||
// Assuming the image was not empty, there should be one last remaining entry that needs to be added.
|
||||
if (current !== null) {
|
||||
// Add the previous image's frame info to the frame map
|
||||
const [imageName, frameInfo] = formatImageData(current);
|
||||
frames[imageName] = frameInfo;
|
||||
}
|
||||
|
||||
const atlasSize = srcMeta.size.split(",").map(v => Number(v));
|
||||
const atlasScale = suffixToScale[image.match(/_([a-z]+)\d*\.png$/)[1]];
|
||||
|
||||
const result = JSON.stringify({
|
||||
frames,
|
||||
meta: {
|
||||
image,
|
||||
format: srcMeta.format,
|
||||
size: {
|
||||
w: atlasSize[0],
|
||||
h: atlasSize[1],
|
||||
},
|
||||
scale: atlasScale.toString(),
|
||||
},
|
||||
});
|
||||
|
||||
const dstFile = join(pathPrefix, image.replace(".png", ".json"));
|
||||
writeFileSync(dstFile, result, {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { convert };
|
||||
|
Loading…
Reference in New Issue
Block a user