199 lines
5.4 KiB
JavaScript
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
|