render update
This commit is contained in:
@@ -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, it’s 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
|
||||
|
||||
Reference in New Issue
Block a user