Added JS engine.
This commit is contained in:
@ -1,56 +0,0 @@
|
||||
const path = require('path');
|
||||
const { imageCreate, imageWrite, imageLoad, imageCopy } = require('./../../utils/image');
|
||||
const fs =require('fs');
|
||||
|
||||
// Where to crop
|
||||
const FACE_AREA = { x: 367, y: 256, width: 280, height: 280 };
|
||||
|
||||
// Where the images are stored
|
||||
const IMAGES_ROOT = path.join(...[
|
||||
'.',
|
||||
'assets',
|
||||
'characters',
|
||||
'penny',
|
||||
'sprites'
|
||||
]);
|
||||
|
||||
// Which image directories to crop
|
||||
const IMAGES_DIRECTORIES = [ 'eyebrows', 'eyes', 'mouths' ];
|
||||
|
||||
(async () => {
|
||||
// Load the base
|
||||
const base = await imageLoad(path.join(IMAGES_ROOT, 'dealer.png'));
|
||||
|
||||
let columnsMax = 0;
|
||||
for(let row = 0; row < IMAGES_DIRECTORIES.length; row++) {
|
||||
const dir = path.join(IMAGES_ROOT, IMAGES_DIRECTORIES[row]);
|
||||
const scan = fs.readdirSync(dir);
|
||||
columnsMax = Math.max(scan.length, columnsMax);
|
||||
}
|
||||
|
||||
// Create the output buffer
|
||||
const out = imageCreate(base.width+(columnsMax*FACE_AREA.width), base.height);
|
||||
|
||||
// Copy the base
|
||||
imageCopy(out, base, 0, 0);
|
||||
|
||||
// Now begin copying the children, row is defined by the directory
|
||||
for(let row = 0; row < IMAGES_DIRECTORIES.length; row++) {
|
||||
const dir = path.join(IMAGES_ROOT, IMAGES_DIRECTORIES[row]);
|
||||
const scan = fs.readdirSync(dir);
|
||||
|
||||
// Column defined by the file index
|
||||
for(let col = 0; col < scan.length; col++) {
|
||||
const img = await imageLoad(path.join(dir, scan[col]));
|
||||
console.log('Copying', scan[col]);
|
||||
|
||||
imageCopy(out, img,
|
||||
base.width+(col*FACE_AREA.width), FACE_AREA.height*row,
|
||||
FACE_AREA
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await imageWrite(out, path.join(IMAGES_ROOT, 'sheet.png'));
|
||||
})().catch(console.error);
|
@ -1,56 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Constants
|
||||
const WORLD_LOAD_TOKEN = ";";
|
||||
const TILE_FLAG_DYNAMIC = 1;
|
||||
|
||||
// Method.
|
||||
const saveWorld = (world) => {
|
||||
const pathWorld = path.join(__dirname, '..', '..', 'assets', world.name);
|
||||
if(!fs.existsSync(pathWorld)) fs.mkdirSync(pathWorld);
|
||||
|
||||
// World string buffer (file data).
|
||||
let strBuffer = "";
|
||||
|
||||
// Header
|
||||
strBuffer += [
|
||||
world.version,
|
||||
world.tileset,
|
||||
""// Seal
|
||||
].join(WORLD_LOAD_TOKEN);
|
||||
|
||||
// Tilemap Definition
|
||||
let buffer = [];
|
||||
for(let i = 0; i < world.tilemap.length; i++) {
|
||||
let tileDef = world.tilemap[i];
|
||||
buffer.push(tileDef.verticeCount+'');
|
||||
buffer.push(tileDef.indiceCount+'');
|
||||
buffer.push(tileDef.flags+'');
|
||||
}
|
||||
strBuffer += buffer.join(WORLD_LOAD_TOKEN);
|
||||
|
||||
fs.writeFileSync(path.join(pathWorld, 'world.txt'), strBuffer);
|
||||
}
|
||||
|
||||
// Worlds.
|
||||
const TILEMAP_WIDTH = 8;
|
||||
const TILEMAP_HEIGHT = 298;
|
||||
|
||||
let world = {
|
||||
version: '1.00',
|
||||
tileset: 'tileset.png',
|
||||
name: 'testworld',
|
||||
tilemap: [ ]
|
||||
};
|
||||
|
||||
for(let i = 0; i < TILEMAP_WIDTH * TILEMAP_HEIGHT; i++) {
|
||||
world.tilemap[i] = {
|
||||
indiceCount: 6,
|
||||
verticeCount: 4,
|
||||
flags: 0
|
||||
};
|
||||
}
|
||||
|
||||
console.log('bruh', world);
|
||||
saveWorld(world);
|
File diff suppressed because it is too large
Load Diff
@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <dawn/dawn.h>
|
||||
#include "../primitive.h"
|
||||
|
||||
#define POKER_CHIP_NAME "Poker Chip"
|
||||
#define POKER_CHIP_VERTICE_COUNT 5249
|
||||
#define POKER_CHIP_INDICE_COUNT 29874
|
||||
#define POKER_CHIP_TRIANGLE_COUNT 9958
|
||||
|
||||
/**
|
||||
* Generated Model Poker Chip
|
||||
* Generated at Sun, 30 May 2021 01:23:51 GMT
|
||||
* @returns Poker Chip as a primitive.
|
||||
*/
|
||||
primitive_t * pokerChipCreate();
|
@ -1,143 +0,0 @@
|
||||
// Copyright (c) 2021 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const MODEL_NAME = 'Poker Chip';
|
||||
const FLIP_TEXTURE_Y = true;
|
||||
|
||||
let rawVertices = [];
|
||||
let faces = [];
|
||||
let coordinates = [];
|
||||
const filePath = path.join(__dirname, '..', '..', 'assets', 'models', 'poker table_del', 'poker_table.obj');
|
||||
const data = fs.readFileSync(filePath, 'utf-8');
|
||||
|
||||
const scale = 0.1;
|
||||
|
||||
data.split('\n').forEach(line => {
|
||||
const bits = line.trim().split(' ');
|
||||
if(!bits.length || bits.every(n => !n || !bits.length)) return;
|
||||
const lineType = bits.shift();
|
||||
|
||||
if(lineType === 'v') {
|
||||
const [ x, y, z ] = bits.map(n => {
|
||||
const val = parseFloat(n) * scale;
|
||||
return val;
|
||||
});
|
||||
rawVertices.push({ x, y, z });
|
||||
} else if(lineType === 'vt') {
|
||||
let [ u, v ] = bits.map(n => parseFloat(n));
|
||||
if(FLIP_TEXTURE_Y) v = 1 - v;
|
||||
coordinates.push({ u, v });
|
||||
} else if(lineType === 'f') {
|
||||
faces.push(bits.map(n => {
|
||||
const [ vertice, coordinate ] = n.split('/').map(n => parseInt(n));
|
||||
return { vertice, coordinate };
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
const verticeCompare = (vl, vr) => (
|
||||
vl.x === vr.x &&
|
||||
vl.y === vr.y &&
|
||||
vl.z === vr.z &&
|
||||
vl.u === vr.u &&
|
||||
vl.v === vr.v
|
||||
);
|
||||
|
||||
const indices = [];
|
||||
const vertices = [];
|
||||
|
||||
faces.forEach(face => {
|
||||
face.forEach(faceIndice => {
|
||||
const rawVert = rawVertices[faceIndice.vertice-1];
|
||||
const rawCoord = coordinates[faceIndice.coordinate-1];
|
||||
const vertice = { ...rawVert, ...rawCoord };
|
||||
|
||||
const indice = vertices.findIndex(vert => {
|
||||
return verticeCompare(vert, vertice);
|
||||
});
|
||||
|
||||
if(indice === -1) {
|
||||
indices.push(vertices.length);
|
||||
vertices.push(vertice);
|
||||
} else {
|
||||
indices.push(indice);
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
const MODEL_NAME_CAPS = MODEL_NAME.replace(/\s/g, '_').toUpperCase();
|
||||
const MODEL_NAME_CAMEL = [
|
||||
MODEL_NAME[0].toLowerCase(),
|
||||
MODEL_NAME.split(' ').join('').substr(1)
|
||||
].join('')
|
||||
// const fn = MODEL_NAME.toLowerCase().split(' ').join('');
|
||||
const fn = 'model';
|
||||
|
||||
const license = `/**
|
||||
* Copyright (c) ${new Date().getFullYear()} Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
`;
|
||||
|
||||
// Write header file
|
||||
const header = `${license}
|
||||
#pragma once
|
||||
#include <dawn/dawn.h>
|
||||
#include "../primitive.h"
|
||||
|
||||
#define ${MODEL_NAME_CAPS}_NAME "${MODEL_NAME}"
|
||||
#define ${MODEL_NAME_CAPS}_VERTICE_COUNT ${vertices.length}
|
||||
#define ${MODEL_NAME_CAPS}_INDICE_COUNT ${indices.length}
|
||||
#define ${MODEL_NAME_CAPS}_TRIANGLE_COUNT ${indices.length/3}
|
||||
|
||||
/**
|
||||
* Generated Model ${MODEL_NAME}
|
||||
* Generated at ${new Date().toUTCString()}
|
||||
* @returns ${MODEL_NAME} as a primitive.
|
||||
*/
|
||||
void ${MODEL_NAME_CAMEL}Init(primitive_t *primitive);
|
||||
`;
|
||||
|
||||
// Write Source file
|
||||
const strVertices = vertices.map((v,i) => {
|
||||
return `{ .x = ${v.x}, .y = ${v.y}, .z = ${v.z}, .u = ${v.u}, .v = ${v.v} }`;
|
||||
}).join(',\n ');
|
||||
|
||||
const strIndices = indices.map(i => {
|
||||
return `${i}`;
|
||||
}).join(',\n ');
|
||||
|
||||
const source = `${license}
|
||||
#include "${fn}.h"
|
||||
|
||||
primitive_t * ${MODEL_NAME_CAMEL}Create(primitive_t *primitive) {
|
||||
vertice_t vertices[${MODEL_NAME_CAPS}_VERTICE_COUNT] = {
|
||||
${strVertices}
|
||||
};
|
||||
|
||||
indice_t indices[${MODEL_NAME_CAPS}_INDICE_COUNT] = {
|
||||
${strIndices}
|
||||
};
|
||||
|
||||
primitiveInit(
|
||||
${MODEL_NAME_CAPS}_VERTICE_COUNT,
|
||||
${MODEL_NAME_CAPS}_INDICE_COUNT
|
||||
);
|
||||
|
||||
primitiveBufferVertices(primitive, 0, ${MODEL_NAME_CAPS}_VERTICE_COUNT, vertices);
|
||||
primitiveBufferIndices(primitive, 0, ${MODEL_NAME_CAPS}_INDICE_COUNT, indices);
|
||||
return primitive;
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
fs.writeFileSync(path.join(__dirname, fn+'.h'), header);
|
||||
fs.writeFileSync(path.join(__dirname, fn+'.c'), source);
|
@ -1,96 +0,0 @@
|
||||
const fs = require("fs");
|
||||
const path = require('path');
|
||||
const { PNG } = require("pngjs");
|
||||
|
||||
// Constants
|
||||
const IMAGES_ROOT = path.join(...[
|
||||
'.',
|
||||
'assets',
|
||||
'characters',
|
||||
'penny',
|
||||
'Sample sets',
|
||||
'Mouth'
|
||||
]);
|
||||
|
||||
const FILE_OUT = path.join(...[
|
||||
'.',
|
||||
'assets',
|
||||
'characters',
|
||||
'penny',
|
||||
'textures',
|
||||
'mouth.png'
|
||||
])
|
||||
|
||||
|
||||
// Code
|
||||
const imageLoad = (image) => new Promise(resolve => {
|
||||
fs.createReadStream(image)
|
||||
.pipe(new PNG({ filterType: 4 }))
|
||||
.on("parsed", function () {
|
||||
// Normalize
|
||||
const pixels = [];
|
||||
for(let y = 0; y < this.height; y++) {
|
||||
for(let x = 0; x < this.width; x++) {
|
||||
const idx = (this.width * y + x) << 2;
|
||||
const r = this.data[idx];
|
||||
const g = this.data[idx + 1];
|
||||
const b = this.data[idx + 2];
|
||||
const a = this.data[idx + 3];
|
||||
|
||||
pixels.push({ r, g, b, a });
|
||||
}
|
||||
}
|
||||
resolve({ pixels, width: this.width, height: this.height });
|
||||
})
|
||||
;
|
||||
});
|
||||
|
||||
const imageWrite = (image, file) => new Promise(resolve => {
|
||||
const png = new PNG({ width: image.width, height: image.height });
|
||||
png.width = image.width;
|
||||
png.height = image.height;
|
||||
|
||||
for(let y = 0; y < image.height; y++) {
|
||||
for(let x = 0; x < image.width; x++) {
|
||||
const i = (image.width * y + x);
|
||||
const idx = i << 2;
|
||||
|
||||
const pixel = image.pixels[i];
|
||||
png.data[idx] = pixel.r;
|
||||
png.data[idx + 1] = pixel.g;
|
||||
png.data[idx + 2] = pixel.b;
|
||||
png.data[idx + 3] = pixel.a;
|
||||
}
|
||||
}
|
||||
|
||||
png.pack().pipe(fs.createWriteStream(file))
|
||||
.on('close', () => resolve(true))
|
||||
;
|
||||
});
|
||||
|
||||
(async () => {
|
||||
const files = fs.readdirSync(IMAGES_ROOT);
|
||||
|
||||
let stitched = null;
|
||||
let k = 0;
|
||||
|
||||
for(let i = 0; i < files.length; i++) {
|
||||
const filePath = path.join(IMAGES_ROOT, files[i]);
|
||||
const image = await imageLoad(filePath);
|
||||
|
||||
if(!stitched) {
|
||||
stitched = {
|
||||
width: image.width,
|
||||
height: image.height * files.length,
|
||||
pixels: Array(image.width*image.height*files.length)
|
||||
}
|
||||
}
|
||||
|
||||
for(let j = 0; j < image.pixels.length; j++) {
|
||||
stitched.pixels[j + (i * image.width * image.height)] = { ...image.pixels[j] };
|
||||
}
|
||||
};
|
||||
|
||||
console.log('Writing');
|
||||
await imageWrite(stitched, FILE_OUT);
|
||||
})().catch(console.error);
|
@ -1,103 +0,0 @@
|
||||
const { PNG } = require("pngjs");
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
/**
|
||||
* Loads an image into memory.
|
||||
* @param image Image to load
|
||||
* @returns A promise that resolves to the loaded image.
|
||||
*/
|
||||
const imageLoad = (image) => new Promise(resolve => {
|
||||
fs.createReadStream(image)
|
||||
.pipe(new PNG({ filterType: 4 }))
|
||||
.on("parsed", function () {
|
||||
// Normalize
|
||||
const pixels = [];
|
||||
for(let y = 0; y < this.height; y++) {
|
||||
for(let x = 0; x < this.width; x++) {
|
||||
const idx = (this.width * y + x) << 2;
|
||||
const r = this.data[idx];
|
||||
const g = this.data[idx + 1];
|
||||
const b = this.data[idx + 2];
|
||||
const a = this.data[idx + 3];
|
||||
|
||||
pixels.push({ r, g, b, a });
|
||||
}
|
||||
}
|
||||
resolve({ pixels, width: this.width, height: this.height });
|
||||
})
|
||||
;
|
||||
});
|
||||
|
||||
/**
|
||||
* Writes an image to an output file.
|
||||
* @param image Image to write.
|
||||
* @param file File to write to.
|
||||
* @returns A promise that, when resolved, has saved the image.
|
||||
*/
|
||||
const imageWrite = (image, file) => new Promise(resolve => {
|
||||
const png = new PNG({ width: image.width, height: image.height });
|
||||
png.width = image.width;
|
||||
png.height = image.height;
|
||||
|
||||
for(let y = 0; y < image.height; y++) {
|
||||
for(let x = 0; x < image.width; x++) {
|
||||
const i = (image.width * y + x);
|
||||
const idx = i << 2;
|
||||
|
||||
const pixel = image.pixels[i];
|
||||
png.data[idx] = pixel.r;
|
||||
png.data[idx + 1] = pixel.g;
|
||||
png.data[idx + 2] = pixel.b;
|
||||
png.data[idx + 3] = pixel.a;
|
||||
}
|
||||
}
|
||||
|
||||
png.pack().pipe(fs.createWriteStream(file))
|
||||
.on('close', () => resolve(true))
|
||||
;
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a blank image
|
||||
* @param width Width of the image.
|
||||
* @param height Height of the image.
|
||||
* @param fill Optional pixel to fill with, defaults to 0,0,0,0
|
||||
* @returns The newly created image.
|
||||
*/
|
||||
const imageCreate = (width, height, pixel) => {
|
||||
if(!pixel || !pixel.r) pixel = { r:0, g:0, b:0, a:0 };
|
||||
const pixels = [];
|
||||
for(let i = 0; i < width * height; i++) pixels.push({ ...pixel });
|
||||
return { pixels, width, height };
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies an area of a source image into a target image.
|
||||
* @param target Target image to copy into.
|
||||
* @param source Source image to copy from.
|
||||
* @param tx Target X position to copy into
|
||||
* @param ty Target Y position to copy into
|
||||
* @param sub Optional source area to use, defined as { x, y, width, height }.
|
||||
*/
|
||||
const imageCopy = (target, source, tx, ty, sub) => {
|
||||
if(!sub) sub = { x: 0, y: 0, width: source.width, height: source.height };
|
||||
|
||||
for(let x = sub.x; x < sub.x+sub.width; x++) {
|
||||
for(let y = sub.y; y < sub.y+sub.height; y++) {
|
||||
let absX = x - sub.x + tx;
|
||||
let absY = y - sub.y + ty;
|
||||
if(absX > target.width || absY > target.height) continue;
|
||||
let ti = absY * target.width + absX;
|
||||
let si = y * source.width + x;
|
||||
target.pixels[ti] = { ...source.pixels[si] };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
imageWrite,
|
||||
imageCreate,
|
||||
imageLoad,
|
||||
imageCopy
|
||||
}
|
Reference in New Issue
Block a user