Files
cell/scripts/graphics.js

199 lines
5.4 KiB
JavaScript

var graphics = this
var io = use('io')
var res = use('resources')
function calc_image_size(img)
{
if (!img.texture || !img.rect) return;
return [img.texture.width*img.rect.width, img.texture.height*img.rect.height];
}
function create_image(path)
{
var data = io.slurpbytes(path);
var newimg;
switch(path.ext()) {
case 'gif':
newimg = graphics.make_gif(data);
if (newimg.surface)
newimg.texture = prosperon.gpu.load_texture(newimg.surface);
else
for (var frame of newimg.frames)
frame.texture = prosperon.gpu.load_texture(frame.surface);
break;
case 'ase':
case 'aseprite':
newimg = graphics.make_aseprite(data);
if (newimg.surface)
newimg.texture = prosperon.gpu.load_texture(newimg.surface);
else {
for (var anim in newimg) {
var a = newimg[anim];
for (var frame of a.frames)
frame.texture = prosperon.gpu.load_texture(frame.surface);
}
}
break;
default:
newimg = {
surface: graphics.make_texture(data)
};
newimg.texture = prosperon.gpu.load_texture(newimg.surface);
break;
}
return newimg;
}
var image = {};
image.dimensions = function()
{
return [this.texture.width, this.texture.height].scale([this.rect[2], this.rect[3]]);
}
var spritesheet;
var sheet_frames = [];
var sheetsize = 1024;
function pack_into_sheet(images)
{
return;
if (!Array.isArray(images)) images = [images];
if (images[0].texture.width > 300 && images[0].texture.height > 300) return;
sheet_frames = sheet_frames.concat(images);
var sizes = sheet_frames.map(x => [x.rect.width*x.texture.width, x.rect.height*x.texture.height]);
var pos = graphics.rectpack(sheetsize, sheetsize, sizes);
if (!pos) {
console.error(`did not make spritesheet properly from images ${images}`);
console.info(sizes);
return;
}
var newsheet = graphics.make_tex_data(sheetsize,sheetsize);
for (var i = 0; i < pos.length; i++) {
// Copy the texture to the new sheet
newsheet.copy(sheet_frames[i].texture, pos[i], sheet_frames[i].rect);
// Update the frame's rect to the new position in normalized coordinates
sheet_frames[i].rect.x = pos[i][0] / newsheet.width;
sheet_frames[i].rect.y = pos[i][1] / newsheet.height;
sheet_frames[i].rect.width = sizes[i][0] / newsheet.width;
sheet_frames[i].rect.height = sizes[i][1] / newsheet.height;
sheet_frames[i].texture = newsheet;
}
newsheet.load_gpu();
spritesheet = newsheet;
return spritesheet;
}
graphics.is_image = function(obj)
{
if (obj.texture && obj.rect) return true;
}
// Any request to it returns an image, which is a texture and rect.
graphics.texture = function texture(path) {
if (typeof path !== 'string') {
return path;
throw new Error('need a string for graphics.texture')
}
var parts = path.split(':');
var ipath = res.find_image(parts[0]);
graphics.texture.cache[ipath] ??= create_image(ipath);
return graphics.texture.cache[ipath];
}
graphics.texture.cache = {};
graphics.texture.time_cache = {};
graphics.texture.total_size = function()
{
var size = 0;
// Object.values(graphics.texture.cache).forEach(x => size += x.texture.inram() ? x..texture.width*x.texture.height*4 : 0);
return size;
}
graphics.texture.total_vram = function()
{
var vram = 0;
// Object.values(graphics.texture.cache).forEach(x => vram += x.vram);
return vram;
}
function merge_objects(ov,nv,arr)
{
arr.forEach(x => ov[x] = nv[x])
}
graphics.tex_hotreload = function tex_hotreload(file) {
console.log(`hot reloading ${file}`)
if (!(file in graphics.texture.cache)) return;
console.log('really doing it')
var img = create_image(file);
var oldimg = graphics.texture.cache[file];
console.log(`new image:${json.encode(img)}`)
console.log(`old image: ${json.encode(oldimg)}`)
merge_objects(oldimg,img, ['surface', 'texture', 'loop', 'time']);
// graphics.texture.cache[file] = img;
};
function make_spritesheet(paths, width, height)
{
return
var textures = paths.map(path => graphics.texture(path));
var sizes = textures.map(tex => [tex.width, tex.height]);
var pos = graphics.rectpack(width, height, sizes);
if (!pos) return;
var sheet = graphics.make_tex_data(width,height);
var st = profile.now();
for (var i = 0; i < pos.length; i++)
sheet.copy(textures[i], pos[i].x, pos[i].y);
sheet.save("spritesheet.qoi");
sheet.load_gpu();
}
var fontcache = {};
var datas= [];
graphics.get_font = function get_font(path,size)
{
var parts = path.split('.');
if (!isNaN(parts[1])) {
path = parts[0];
size = Number(parts[1]);
}
var fullpath = res.find_font(path);
if (!fullpath) throw new Error(`Cannot load font ${path}`)
var fontstr = `${fullpath}.${size}`;
if (fontcache[fontstr]) return fontcache[fontstr];
var data = io.slurpbytes(fullpath);
fontcache[fontstr] = graphics.make_font(data,size);
fontcache[fontstr].texture = prosperon.gpu.load_texture(fontcache[fontstr].surface);
return fontcache[fontstr];
}
graphics.queue_sprite_mesh = function(queue)
{
var sprites = queue.filter(x => x.type === 'sprite');
if (sprites.length === 0) return [];
var mesh = graphics.make_sprite_mesh(sprites);
for (var i = 0; i < sprites.length; i++) {
sprites[i].mesh = mesh;
sprites[i].first_index = i*6;
sprites[i].num_indices = 6;
}
return [mesh.pos,mesh.uv,mesh.color,mesh.indices]
}
return graphics