render update

This commit is contained in:
2025-07-27 17:08:29 -05:00
parent d5789598a0
commit 5ae95aee01
5 changed files with 232 additions and 503 deletions

View File

@@ -1,54 +1,18 @@
var graphics = this
graphics[cell.DOC] = `
Provides functionality for loading and managing images, fonts, textures, and sprite meshes.
Includes both JavaScript and C-implemented routines for creating geometry buffers, performing
rectangle packing, etc.
`
var renderer_actor = arg?.[0] || null
var io = use('io')
var time = use('time')
var res = use('resources')
var json = use('json')
var os = use('os')
var GPU = Symbol()
var CPU = Symbol()
var LASTUSE = Symbol()
var LOADING = Symbol()
var cache = {}
var pending_gpu_loads = []
graphics.setup = function(renderer)
{
renderer_actor = renderer
// Process any pending GPU loads
if (renderer_actor && pending_gpu_loads.length > 0) {
log.console(`Processing ${pending_gpu_loads.length} pending GPU loads`)
for (var img of pending_gpu_loads) {
img.loadGPU()
}
pending_gpu_loads = []
}
// Also process any cached images that need GPU loading
if (renderer_actor) {
for (var key in cache) {
var img = cache[key]
if (img instanceof graphics.Image && img.cpu && img.gpu == 0) {
img.loadGPU()
}
}
}
}
// Image constructor function
// cpu is the surface
graphics.Image = function(surfaceData) {
// Initialize properties
this.cpu = surfaceData || null;
this.gpu = 0;
this.texture = 0;
@@ -58,40 +22,6 @@ graphics.Image = function(surfaceData) {
this.rect = {x:0, y:0, width:this.width, height:this.height};
this[LOADING] = false;
this[LASTUSE] = time.number();
// Load GPU texture if renderer is available, otherwise queue it
if (renderer_actor && this.cpu) {
this.loadGPU();
} else if (this.cpu) {
// Queue for later GPU loading when renderer is available
pending_gpu_loads.push(this)
}
}
graphics.Image.prototype.loadGPU = function() {
if (!this[LOADING] && renderer_actor && this.cpu) {
this[LOADING] = true;
var self = this;
send(renderer_actor, {
kind: "renderer",
op: "loadTexture",
data: this.cpu
}, function(response) {
if (response.error) {
log.error("Failed to load texture:")
log.error(response.error)
self[LOADING] = false;
} else {
// Store the full response as texture (has width/height)
self.texture = response;
// Store just the ID as gpu
self.gpu = response.id || response;
decorate_rect_px(self);
self[LOADING] = false;
}
});
}
}
// Add methods to prototype
@@ -197,19 +127,13 @@ function create_image(path){
return makeAnim(wrapFrames(raw), true);
}
/* ── Case C: ASE helpers returned { animName:{frames,loop}, … } or single frame ── */
if(typeof raw == 'object' && !raw.width) {
// Check if it's a single surface from ASE (single frame, no tags)
if(raw.surface) {
if(raw.surface)
return new graphics.Image(raw.surface)
}
// Check if it's an untagged animation (multiple frames, no tags)
// This happens when ASE has no tags but multiple frames
if(raw.frames && Array.isArray(raw.frames) && raw.loop != null)
return makeAnim(wrapFrames(raw.frames), !!raw.loop);
// Multiple named animations from ASE (with tags)
def anims = {};
for(def [name, anim] of Object.entries(raw)){
if(anim && Array.isArray(anim.frames))
@@ -240,9 +164,6 @@ image.dimensions = function() {
}
return [width, height].scale([this.rect[2], this.rect[3]])
}
image.dimensions[cell.DOC] = `
:return: A 2D array [width, height] that is the scaled size of this image (texture size * rect size).
`
var spritesheet
var sheet_frames = []
@@ -261,10 +182,6 @@ function pack_into_sheet(images) {
graphics.is_image = function(obj) {
if (obj.texture && obj.rect) return true
}
graphics.is_image[cell.DOC] = `
:param obj: An object to check.
:return: True if 'obj' has a .texture and a .rect property, indicating it's an image object.
`
graphics.texture_from_data = function(data)
{
@@ -278,7 +195,7 @@ graphics.texture_from_data = function(data)
return img;
}
graphics.from_surface = function(id, surf)
graphics.from_surface = function(surf)
{
return make_handle(surf)
}
@@ -388,32 +305,20 @@ graphics.texture = function texture(path) {
return cached
}
graphics.texture[cell.DOC] = `
:param path: A string path to an image file or an already-loaded image object.
:return: An image object with {surface, texture, frames?, etc.} depending on the format.
Load or retrieve a cached image, converting it into a GPU texture. If 'path' is already an object, its returned directly.
`
graphics.texture.total_size = function() {
var size = 0
// Not yet implemented, presumably sum of (texture.width * texture.height * 4) for images in RAM
return size
}
graphics.texture.total_size[cell.DOC] = `
:return: The total estimated memory size of all cached textures in RAM, in bytes. (Not yet implemented.)
`
graphics.texture.total_vram = function() {
var vram = 0
// Not yet implemented, presumably sum of GPU memory usage
return vram
}
graphics.texture.total_vram[cell.DOC] = `
:return: The total estimated GPU memory usage of all cached textures, in bytes. (Not yet implemented.)
`
graphics.tex_hotreload = function tex_hotreload(file) {
// Extract just the filename without path and extension
var basename = file.split('/').pop().split('.')[0]
// Check if this basename exists in our cache
@@ -445,17 +350,7 @@ graphics.tex_hotreload = function tex_hotreload(file) {
oldimg.rect = {x:0, y:0, width:img.cpu.width, height:img.cpu.height}
decorate_rect_px(oldimg)
}
// If the texture was on GPU, trigger reload
if (oldGPU && renderer_actor) {
oldimg.loadGPU()
}
}
graphics.tex_hotreload[cell.DOC] = `
:param file: The file path that was changed on disk.
:return: None
Reload the image for the given file, updating the cached copy in memory and GPU.
`
/**
Merges specific properties from nv into ov, using an array of property names.
@@ -494,21 +389,6 @@ graphics.get_font = function get_font(path) {
var data = io.slurpbytes(fullpath)
var font = graphics.make_font(data, size)
// Load font texture via renderer actor (async)
if (renderer_actor) {
send(renderer_actor, {
kind: "renderer",
op: "loadTexture",
data: font.surface
}, function(response) {
if (response.error) {
log.error("Failed to load font texture:", response.error);
} else {
font.texture = response;
}
});
}
fontcache[fontstr] = font
return font