This commit is contained in:
2025-12-19 16:42:40 -06:00
parent 4bdbde52a0
commit 45e2fc7f2c
50 changed files with 481 additions and 60612 deletions

View File

@@ -1,4 +1,4 @@
var graphics = this
var graphics = {}
var io = use('cellfs')
var time = use('time')
@@ -6,7 +6,10 @@ var res = use('resources')
var json = use('json')
var os = use('os')
var staef = use('staef')
var qoi = use('qoi')
var qoi = use('image/qoi')
var png = use('image/png')
var gif = use('image/gif')
var aseprite = use('image/aseprite')
var LASTUSE = "graphics:lastuse"
var LOADING = "graphics:loading"
@@ -94,16 +97,59 @@ function makeAnim(frames, loop=true){
function decode_image(bytes, ext)
{
switch(ext) {
case 'gif': return graphics.make_gif(bytes) // returns array of surfaces
case 'gif': return decode_gif(gif.decode(bytes))
case 'ase':
case 'aseprite': return graphics.make_aseprite(bytes)
case 'aseprite': return decode_aseprite(aseprite.decode(bytes))
case 'qoi': return qoi.decode(bytes) // returns single surface
case 'png': return png.decode(bytes) // returns single surface
case 'jpg':
case 'jpeg': return png.decode(bytes) // png.decode handles jpg too via stb_image
case 'bmp': return png.decode(bytes) // png.decode handles bmp too via stb_image
default:
// Try QOI first since it's fast to check
var qoi_result = qoi.decode(bytes)
if (qoi_result) return qoi_result
// Fall back to make_texture for other formats
return graphics.image_decode(bytes) // returns single surface
// Fall back to png decoder for other formats (uses stb_image)
return png.decode(bytes)
}
}
// Convert gif.decode output to graphics.cm format
function decode_gif(decoded) {
if (!decoded || !decoded.frames) return null
// Single frame - return just the surface
if (decoded.frame_count == 1) {
return decoded.frames[0]
}
// Multiple frames - return array with time property
return decoded.frames.map(function(frame) {
return {
surface: frame,
time: (frame.duration || 100) / 1000.0 // convert ms to seconds
}
})
}
// Convert aseprite.decode output to graphics.cm format
function decode_aseprite(decoded) {
if (!decoded) return null
// Single frame - return just the surface
if (decoded.frame_count == 1) {
return { surface: decoded.frames[0] }
}
// Multiple frames without tags - return as single animation
return {
frames: decoded.frames.map(function(frame) {
return {
surface: frame,
time: (frame.duration || 100) / 1000.0 // convert ms to seconds
}
}),
loop: true
}
}
@@ -223,7 +269,7 @@ graphics.texture = function texture(path) {
var frameIndex = parts[2]
// Handle the case where animName is actually a frame index (e.g., "gears:0")
if (animName != null && frameIndex == null && !isNaN(number(animName))) {
if (animName != null && frameIndex == null && !isa(number(animName), null)) {
frameIndex = number(animName)
animName = null
}
@@ -250,7 +296,7 @@ graphics.texture = function texture(path) {
// If cached is a single animation (has .frames property)
if (cached.frames && isa(cached.frames, array)) {
var idx = number(frameIndex)
if (isNaN(idx)) return cached
if (idx == null) return cached
// Wrap the index
idx = idx % cached.frames.length
return cached.frames[idx].image
@@ -366,13 +412,18 @@ var fontcache = {}
var datas = []
graphics.get_font = function get_font(path) {
if (typeof path != 'string') return path
if (isa(path, object)) return path
if (!isa(path, text))
throw new Error(`Can't find font with path: ${path}`)
var parts = path.split('.')
var size = 16 // default size
if (!isNaN(parts[1])) {
parts[1] = number(parts[1])
if (parts[1]) {
path = parts[0]
size = Number(parts[1])
size = parts[1]
}
var fullpath = res.find_font(path)
if (!fullpath) throw new Error(`Cannot load font ${path}`)