fix qr decoding

This commit is contained in:
2025-05-06 12:48:13 -05:00
parent 938da0d4dc
commit 92f56570d9
9 changed files with 421 additions and 156 deletions

View File

@@ -1,12 +1,3 @@
/* Sprite façade (JS) ↔ struct sprite (C)
* The C side exposes per-field getters/setters plus
* `set_affine(m)` which (re)calculates the 2×2 matrix from
* scale / skew / rotation.
* We mirror every exposed field and make sure the C
* matrix is refreshed whenever one of the three factors
* changes.
*/
var sprite = {}
var graphics = use('graphics')
@@ -20,6 +11,7 @@ var SCALE = Symbol()
var SKEW = Symbol()
var CENTER = Symbol()
var COLOR = Symbol()
var IMAGE = Symbol()
var ursprite = {
get pos() { return this[POS] },
@@ -64,36 +56,35 @@ var ursprite = {
this[SPRITE].color = v
},
move(mv){
this.pos = {x:this.pos.x+mv.x, y:this.pos.y+mv.y}
},
move(mv) { this[SPRITE].move(mv) },
moveto(p){
this.pos = p
},
get image() { return this[IMAGE] },
set image(img) {
this[IMAGE] = img
this[SPRITE].set_image(img)
}
}
var _sprites = []
sprite.create = function(image, pos, anchor=[0,0], layer=0, props={}) {
var def_sprite = Object.freeze({
pos: [0,0],
rotation: 0,
scale: [1,1],
center: [0,0],
color: [1,1,1,1],
skew: [0,0],
layer: 0,
})
sprite.create = function(image, info) {
info.__proto__ = def_sprite
var sp = Object.create(ursprite)
var raw = graphics.make_sprite()
sp[SPRITE] = raw
sp.pos = pos
sp.rotation = 0
sp.scale = [1,1]
sp.skew = [0,0]
sp.center = anchor
sp.color = [1,1,1,1]
var tex = graphics.texture(image)
raw.set_image(tex)
sp.image = tex
sp.layer = layer
sp.props = props
sp.anchor = anchor
sp[SPRITE] = graphics.make_sprite(info)
sp.image = graphics.texture(image)
_sprites.push(sp)
return sp
@@ -102,6 +93,14 @@ sprite.create = function(image, pos, anchor=[0,0], layer=0, props={}) {
sprite.forEach = fn => { for (let s of _sprites) fn(s) }
sprite.values = () => _sprites.slice()
sprite.geometry= () => graphics.make_sprite_mesh(_sprites)
sprite.queue = () => graphics.make_sprite_queue(_sprites)
var raws = []
sprite.queue = function() {
if (raws.length != _sprites.length)
raws.length = _sprites.length
for (var i = 0; i < _sprites.length; i++) raws[i] = _sprites[i]
return graphics.make_sprite_queue(_sprites.map(x => x[SPRITE]))
}
return sprite

View File

@@ -53,8 +53,8 @@ var current_color = Color.white
render.image = function(image, rect, rotation, anchor, shear, info)
{
rect.width = image.rect_px.width;
rect.height = image.rect_px.height;
// rect.width = image.rect_px.width;
// rect.height = image.rect_px.height;
context.texture(image.texture, image.rect_px, rect, rotation, anchor);
}

View File

@@ -3147,8 +3147,10 @@ JSC_CCALL(renderer_sprite,
sprite sp = js_getsprite(js, argv[0]);
SDL_Texture *tex;
JS_GETATOM(js, tex, sp.image, texture, SDL_Texture);
rect uv;
JS_GETATOM(js, uv, sp.image, rect, rect);
float w = sp.uv.w, h = sp.uv.h;
float w = uv.w, h = uv.h;
HMM_Vec2 tl_local = { -sp.center.X, -sp.center.Y };
HMM_Vec2 tr_local = { -sp.center.X + w, -sp.center.Y };
@@ -3162,7 +3164,7 @@ JSC_CCALL(renderer_sprite,
SDL_FPoint right = renderer_world_to_screen(ctx, world_tr);
SDL_FPoint down = renderer_world_to_screen(ctx, world_bl);
if (!SDL_RenderTextureAffine(ctx->sdl, tex, &sp.uv, &origin, &right, &down))
if (!SDL_RenderTextureAffine(ctx->sdl, tex, &uv, &origin, &right, &down))
return JS_ThrowInternalError(js, "Render sprite error: %s", SDL_GetError());
)
@@ -4146,6 +4148,9 @@ JSC_CCALL(gpu_make_sprite_queue,
JS_DupValue(js,sprites[i].image);
} else {
quads = js_arrlen(js, argv[0]);
if (quads == 0)
return JS_ThrowReferenceError(js, "Expected an array of sprites with length > 0.");
arrsetcap(sprites, quads);
for (int i = 0; i < quads; i++) {
@@ -4161,10 +4166,10 @@ JSC_CCALL(gpu_make_sprite_queue,
JS_GETATOM(js, sp.center, sub, center, vec2)
JS_GETATOM(js, sp.skew, sub, skew, vec2)
JS_GETATOM(js, sp.scale, sub, scale, vec2)
JS_GETATOM(js,sp.color,sub,color,color)
JS_GETATOM(js,sp.layer,sub,layer,number)
JS_GETATOM(js,sp.uv,sub,src,rect)
JS_GETATOM(js, sp.color,sub,color,color)
JS_GETATOM(js, sp.layer,sub,layer,number)
sp.image = JS_GetProperty(js,sub,image);
sprite_apply(&sp);
arrput(sprites,sp);
}
JS_FreeValue(js, sub);
@@ -4175,27 +4180,49 @@ JSC_CCALL(gpu_make_sprite_queue,
struct quad_buffers buffers = quad_buffers_new(quads*4);
for (int i = 0; i < quads; i++) {
rect pr = {0};
rect uv = sprites[i].uv;
HMM_Vec4 c = sprites[i].color;
const HMM_Vec2 local[4] = { {0,0}, {1,0}, {0,1}, {1,1} };
int idx = i * 4;
rect uv;
rect uv_px;
JSValue cur_img = JS_UNDEFINED;
buffers.pos[idx + 0] = (HMM_Vec2){ pr.x, pr.y };
buffers.pos[idx + 1] = (HMM_Vec2){ pr.x+pr.w, pr.y };
buffers.pos[idx + 2] = (HMM_Vec2){ pr.x, pr.y+pr.h };
buffers.pos[idx + 3] = (HMM_Vec2){ pr.x+pr.w, pr.y+pr.h };
for (size_t i = 0; i < quads; i++) {
sprite *s = &sprites[i];
if (JS_IsUndefined(cur_img) || !JS_StrictEq(js, s->image, cur_img)) {
cur_img = s->image;
JS_GETATOM(js, uv, cur_img, rect, rect)
JS_GETATOM(js, uv_px, cur_img, rect_px, rect)
}
buffers.uv[idx + 0] = (HMM_Vec2){ uv.x, uv.y+uv.h };
buffers.uv[idx + 1] = (HMM_Vec2){ uv.x+uv.w, uv.y+uv.h };
buffers.uv[idx + 2] = (HMM_Vec2){ uv.x, uv.y };
buffers.uv[idx + 3] = (HMM_Vec2){ uv.x+uv.w, uv.y };
HMM_Vec2 px_size = {
uv_px.w * s->scale.X,
uv_px.h * s->scale.Y
};
buffers.color[idx + 0] = c;
buffers.color[idx + 1] = c;
buffers.color[idx + 2] = c;
buffers.color[idx + 3] = c;
HMM_Vec2 anchor = {
px_size.X * s->center.X,
px_size.Y * s->center.Y
};
size_t base = i * 4;
for (int v = 0; v < 4; v++) {
HMM_Vec2 lp = {
local[v].X * px_size.X - anchor.X,
local[v].Y * px_size.Y - anchor.Y
};
HMM_Vec2 world = HMM_AddV2(s->pos, HMM_MulM2V2(s->affine, lp));
buffers.pos[base + v] = world;
buffers.color[base + v] = s->color;
}
/* UVs are still top-left-origin pixel coords, so keep previous packing */
buffers.uv[base + 0] = (HMM_Vec2){ uv.x, uv.y + uv.h };
buffers.uv[base + 1] = (HMM_Vec2){ uv.x + uv.w, uv.y + uv.h };
buffers.uv[base + 2] = (HMM_Vec2){ uv.x, uv.y };
buffers.uv[base + 3] = (HMM_Vec2){ uv.x + uv.w, uv.y };
}
JSValue mesh = quadbuffers_to_mesh(js, buffers);
@@ -5407,6 +5434,51 @@ static const JSCFunctionListEntry js_SDL_GPUComputePass_funcs[] = {
MIST_FUNC_DEF(compute, storage_textures, 2),
};
typedef struct { const char *name; SDL_PixelFormat fmt; } fmt_entry;
static const fmt_entry k_fmt_table[] = {
{ "rgba32", SDL_PIXELFORMAT_RGBA32 },
{ "argb32", SDL_PIXELFORMAT_ARGB32 },
{ "bgra32", SDL_PIXELFORMAT_BGRA32 },
{ "abgr32", SDL_PIXELFORMAT_ABGR32 },
{ "rgb565", SDL_PIXELFORMAT_RGB565 },
{ "bgr565", SDL_PIXELFORMAT_BGR565 },
{ "rgb24", SDL_PIXELFORMAT_RGB24 },
{ "bgr24", SDL_PIXELFORMAT_BGR24 },
{ "rgb332", SDL_PIXELFORMAT_RGB332 },
{ "rgba64", SDL_PIXELFORMAT_RGBA64 },
{ "rgb48", SDL_PIXELFORMAT_RGB48 },
{ NULL, SDL_PIXELFORMAT_UNKNOWN }
};
static JSValue pixelformat2js(JSContext *js, SDL_PixelFormat fmt)
{
fmt_entry *it;
for (it = k_fmt_table; it->name; it++)
if (it->fmt == fmt)
break;
if (it->name)
return JS_NewString(js, it->name);
return JS_UNDEFINED;
}
static SDL_PixelFormat js2pixelformat(JSContext *js, JSValue v)
{
if (JS_IsUndefined(v)) return SDL_PIXELFORMAT_UNKNOWN;
const char *s = JS_ToCString(js, v);
if (!s) return SDL_PIXELFORMAT_UNKNOWN;
fmt_entry *it;
for (it = k_fmt_table; it->name; it++)
if (!strcmp(it->name, s))
break;
JS_FreeCString(js,s);
return it->fmt;
}
JSC_CCALL(surface_blit,
SDL_Surface *dst = js2SDL_Surface(js,self);
rect dstrect = js2rect(js,argv[0]);
@@ -5461,21 +5533,79 @@ JSC_CCALL(surface_rect,
SDL_FillSurfaceRect(dst,&r,SDL_MapRGBA(&pdetails,NULL, color.r*255,color.g*255,color.b*255,color.a*255));
)
JSC_CCALL(surface_convert,
SDL_Surface *surf = js2SDL_Surface(js,self);
SDL_PixelFormat fmt = js2pixelformat(js, argv[0]);
SDL_Surface *dst = SDL_ConvertSurface(surf, fmt);
if (!dst) return JS_ThrowInternalError(js, "Convert failed: %s", SDL_GetError());
return SDL_Surface2js(js, dst);
)
JSC_CCALL(surface_dup,
SDL_Surface *surf = js2SDL_Surface(js,self);
SDL_Surface *conv = SDL_ConvertSurface(surf, SDL_PIXELFORMAT_RGBA8888);
SDL_Surface *conv = SDL_DuplicateSurface(surf);
if (!conv)
return JS_ThrowReferenceError(js, "could not blit to dup'd surface: %s", SDL_GetError());
return SDL_Surface2js(js,conv);
)
JSC_CCALL(surface_pixels,
SDL_Surface *surf = js2SDL_Surface(js,self);
/* if (SDL_ISPIXELFORMAT_FOURCC(surf->format->format))
return JS_ThrowTypeError(js, "planar or FOURCC formats are not supported - convert first");
*/
int locked = 0;
if (SDL_MUSTLOCK(surf)) {
if (SDL_LockSurface(surf) < 0)
return JS_ThrowInternalError(js, "Lock surface failed: %s", SDL_GetError());
locked = 1;
}
size_t byte_size = surf->pitch*surf->h;
ret = JS_NewArrayBufferCopy(js, surf->pixels, byte_size);
if (locked)
SDL_UnlockSurface(surf);
)
JSC_CCALL(surface_width,
SDL_Surface *s = js2SDL_Surface(js,self);
return JS_NewFloat64(js, s->w);
)
JSC_CCALL(surface_height,
SDL_Surface *s = js2SDL_Surface(js,self);
return JS_NewFloat64(js, s->h);
)
JSC_CCALL(surface_format,
SDL_Surface *s = js2SDL_Surface(js,self);
return pixelformat2js(js, s->format);
)
JSC_CCALL(surface_pitch,
SDL_Surface *s = js2SDL_Surface(js,self);
return JS_NewFloat64(js, s->pitch);
)
static const JSCFunctionListEntry js_SDL_Surface_funcs[] = {
MIST_FUNC_DEF(surface, blit, 3),
MIST_FUNC_DEF(surface, scale, 1),
MIST_FUNC_DEF(surface,fill,1),
MIST_FUNC_DEF(surface,rect,2),
MIST_FUNC_DEF(surface, dup, 0),
MIST_FUNC_DEF(surface, pixels, 0),
MIST_FUNC_DEF(surface, convert, 1),
MIST_FUNC_DEF(surface, width, 0),
MIST_FUNC_DEF(surface, height, 0),
MIST_FUNC_DEF(surface, format, 0),
MIST_FUNC_DEF(surface, pitch, 0),
};
JSC_CCALL(camera_frame,
@@ -6419,22 +6549,20 @@ JSC_CCALL(os_make_texture,
if (!raw) return JS_ThrowReferenceError(js, "could not load texture with array buffer");
int n, width, height;
void *data = stbi_load_from_memory(raw, len, &width, &height, &n, 0);
void *data = stbi_load_from_memory(raw, len, &width, &height, &n, 4);
if (data == NULL)
return JS_ThrowReferenceError(js, "no known image type from pixel data");
if (!data)
return JS_ThrowReferenceError(js, "no known image type from pixel data: %s", stbi_failure_reason());
int FMT = 0;
if (n == 4)
FMT = SDL_PIXELFORMAT_RGBA32;
else if (n == 3)
FMT = SDL_PIXELFORMAT_RGB24;
else {
if (width <= 0 || height <= 0) {
free(data);
return JS_ThrowReferenceError(js, "unknown pixel format. got %d channels", n);
return JS_ThrowReferenceError(js, "decoded image has invalid size: %dx%d", width, height);
}
SDL_Surface *surf = SDL_CreateSurfaceFrom(width,height,FMT, data, width*n);
int pitch = width*4;
int fmt = SDL_PIXELFORMAT_RGBA32;
SDL_Surface *surf = SDL_CreateSurfaceFrom(width,height,fmt, data, pitch);
if (!surf) {
free(data);
return JS_ThrowReferenceError(js, "Error creating surface from data: %s",SDL_GetError());
@@ -6592,7 +6720,18 @@ JSC_CCALL(os_make_transform,
// t->self = JS_DupValue(js,ret);
t->self = ret;
)
JSC_CCALL(os_make_sprite, return sprite2js(js,make_sprite()))
JSC_CCALL(os_make_sprite,
sprite *sp = make_sprite();
JS_GETATOM(js, sp->pos, argv[0], pos, vec2)
JS_GETATOM(js, sp->center, argv[0], center, vec2)
JS_GETATOM(js, sp->skew, argv[0], skew, vec2)
JS_GETATOM(js, sp->scale, argv[0], scale, vec2)
JS_GETATOM(js, sp->rotation, argv[0], rotation, angle)
JS_GETATOM(js, sp->layer, argv[0], layer, number)
JS_GETATOM(js, sp->color, argv[0], color, color)
sprite_apply(sp);
return sprite2js(js,sp);
)
JSC_SCALL(os_system, ret = number2js(js,system(str)); )
@@ -7139,6 +7278,26 @@ static const JSCFunctionListEntry js_util_funcs[] = {
MIST_FUNC_DEF(os, insertion_sort, 2),
};
JSC_CCALL(graphics_hsl_to_rgb,
float h, s, l;
JS_ToFloat64(js, &h, argv[0]);
JS_ToFloat64(js, &s, argv[1]);
JS_ToFloat64(js, &l, argv[2]);
float c = (1 - abs(2 * l - 1)) * s;
float x = c * (1 - abs(fmod((h/60),2) - 1));
float m = l - c / 2;
float r = 0, g = 0, b = 0;
if (h < 60) { r = c; g = x; }
else if (h < 120) { r = x; g = c; }
else if (h < 180) { g = c; b = x; }
else if (h < 240) { g = x; b = c; }
else if (h < 300) { r = x; b = c; }
else { r = c; b = x; }
return color2js(js, (colorf){r+m, g+m, b+m, 1});
)
static const JSCFunctionListEntry js_graphics_funcs[] = {
MIST_FUNC_DEF(gpu, make_sprite_mesh, 2),
MIST_FUNC_DEF(gpu, make_sprite_queue, 4),
@@ -7152,8 +7311,9 @@ static const JSCFunctionListEntry js_graphics_funcs[] = {
MIST_FUNC_DEF(os, make_surface, 1),
MIST_FUNC_DEF(os, make_cursor, 1),
MIST_FUNC_DEF(os, make_font, 2),
MIST_FUNC_DEF(os, make_sprite, 0),
MIST_FUNC_DEF(os, make_sprite, 1),
MIST_FUNC_DEF(os, make_line_prim, 5),
MIST_FUNC_DEF(graphics, hsl_to_rgb, 3),
};
static const JSCFunctionListEntry js_video_funcs[] = {
@@ -7362,6 +7522,13 @@ JSC_GETSET(sprite, skew, vec2)
JSC_GETSET(sprite, scale, vec2)
JSC_GETSET(sprite, rotation, number)
JSC_CCALL(sprite_move,
sprite *sp = js2sprite(js,self);
HMM_Vec2 mv = js2vec2(js,argv[0]);
sp->pos.x += mv.x;
sp->pos.y += mv.y;
)
JSC_CCALL(sprite_set_affine,
sprite *sp = js2sprite(js,self);
sprite_apply(sp);
@@ -7371,21 +7538,20 @@ JSC_CCALL(sprite_set_image,
sprite *sp = js2sprite(js,self);
if (!JS_IsUndefined(sp->image))
JS_FreeValue(js,sp->image);
sp->image = JS_DupValue(js,argv[0]);
if (JS_IsUndefined(sp->image)) return JS_UNDEFINED;
JSValue img = sp->image;
JS_GETATOM(js, sp->uv, img, rect, rect)
sp->image = JS_DupValue(js, argv[0]);
)
static const JSCFunctionListEntry js_sprite_funcs[] = {
MIST_FUNC_DEF(sprite, set_affine, 0),
MIST_FUNC_DEF(sprite, set_image, 1),
CGETSET_ADD(sprite, skew),
CGETSET_ADD(sprite, rotation),
CGETSET_ADD(sprite, pos),
CGETSET_ADD(sprite, center),
CGETSET_ADD(sprite, layer),
CGETSET_ADD(sprite, color),
MIST_FUNC_DEF(sprite, move, 1),
JS_CGETSET_DEF("pos", js_sprite_get_pos, js_sprite_set_pos),
JS_CGETSET_DEF("scale", js_sprite_get_scale, js_sprite_set_scale),
JS_CGETSET_DEF("skew", js_sprite_get_skew, js_sprite_set_skew),
JS_CGETSET_DEF("layer", js_sprite_get_layer, js_sprite_set_layer),
JS_CGETSET_DEF("color", js_sprite_get_color, js_sprite_set_color),
JS_CGETSET_DEF("center", js_sprite_get_center, js_sprite_set_center),
JS_CGETSET_DEF("rotation", js_sprite_get_rotation, js_sprite_set_rotation),
};
#define JSSTATIC(NAME, PARENT) \

View File

@@ -591,6 +591,7 @@ void script_startup(prosperon_rt *prt)
JS_AddIntrinsicJSON(js);
JS_AddIntrinsicMapSet(js);
JS_AddIntrinsicTypedArrays(js);
JS_AddIntrinsicWeakRef(js);
JS_SetContextOpaque(js, prt);
prt->context = js;

View File

@@ -125,43 +125,69 @@ static JSValue js_qr_encode(JSContext *js, JSValueConst this_val, int argc, JSVa
return result;
}
static uint8_t rgba_to_gray(uint8_t r, uint8_t g, uint8_t b)
{
return (uint8_t)(( 299 * r + 587 * g + 114 * b + 500) / 1000);
}
// QR decode function (unchanged)
static JSValue js_qr_decode(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
size_t data_len;
uint8_t *data;
if (argc < 1 || !(data = JS_GetArrayBuffer(js, &data_len, argv[0]))) {
uint8_t *src;
int w, h, pitch;
src = JS_GetArrayBuffer(js, &data_len, argv[0]);
if (!src)
return JS_ThrowTypeError(js, "decode expects an ArrayBuffer");
}
JS_ToInt32(js, &w, argv[1]);
JS_ToInt32(js, &h, argv[2]);
JS_ToInt32(js, &pitch, argv[3]);
if (w <= 0 || h <= 0)
return JS_ThrowInternalError(js, "Bad width or height: %dx%d", w, h);
struct quirc *qr = quirc_new();
if (!qr) {
if (!qr)
return JS_ThrowInternalError(js, "Failed to initialize QR decoder");
}
int width = (int)sqrt((double)data_len);
if (width * width != (int)data_len) {
if (quirc_resize(qr, w, h) < 0) {
quirc_destroy(qr);
return JS_ThrowTypeError(js, "ArrayBuffer must represent a square image");
return JS_ThrowInternalError(js, "quirc_resize failed");
}
if (quirc_resize(qr, width, width) < 0) {
quirc_destroy(qr);
return JS_ThrowInternalError(js, "Failed to resize QR decoder");
uint8_t *dst = quirc_begin(qr, NULL, NULL);
printf("decoding image size %dx%d, pitch %d and size %d\n", w, h, pitch, data_len);
for (int y = 0; y < h; ++y) {
uint8_t *row = src + y * pitch;
uint8_t *out = dst + y * w;
for (int x = 0; x < w; ++x) {
uint8_t a = row[x*4 + 3]; /* alpha */
if (a < 128) { /* mostly transparent */
out[x] = 255;
} else {
uint8_t r = row[x*4+0];
uint8_t g = row[x*4+1];
uint8_t b = row[x*4+2];
out[x] = rgba_to_gray(r, g, b);
}
}
}
int h;
uint8_t *image = quirc_begin(qr, &width, &h);
memcpy(image, data, data_len);
quirc_end(qr);
int count = quirc_count(qr);
JSValue result = JS_NewArray(js);
printf("found %d codes\n", count);
for (int i = 0; i < count; i++) {
struct quirc_code code;
struct quirc_data qdata;
quirc_extract(qr, i, &code);
printf("code is %p\n", code.size);
if (quirc_decode(&code, &qdata) == QUIRC_SUCCESS) {
JSValue item = JS_NewStringLen(js, (const char *)qdata.payload, qdata.payload_len);
JS_SetPropertyUint32(js, result, i, item);
@@ -175,7 +201,7 @@ static JSValue js_qr_decode(JSContext *js, JSValueConst this_val, int argc, JSVa
// Exported functions for the module
static const JSCFunctionListEntry js_qr_funcs[] = {
JS_CFUNC_DEF("encode", 2, js_qr_encode), // Updated to expect 2 args
JS_CFUNC_DEF("decode", 1, js_qr_decode),
JS_CFUNC_DEF("decode", 4, js_qr_decode),
};
// Helper to return the default export object

View File

@@ -15,18 +15,15 @@ void sprite_free(JSRuntime *rt, sprite *sprite)
void sprite_apply(sprite *sp)
{
/* -------- rotation + skew → 2×2 affine matrix -------- */
float rot = sp->rotation;
HMM_Vec2 k = sp->skew;
HMM_Vec2 s = sp->scale;
float c = cosf(rot), si = sinf(rot);
float c = cosf(rot), s = sinf(rot);
sp->affine.Columns[0] = (HMM_Vec2){
.x = (c + k.x * si) * s.x,
.y = (k.y * c + si) * s.x
};
sp->affine.Columns[1] = (HMM_Vec2){
.x = (-si + k.x * c) * s.y,
.y = (-k.y * si + c) * s.y
};
sp->affine.Columns[0] = (HMM_Vec2){ .x = c + k.x * s,
.y = k.y * c + s };
sp->affine.Columns[1] = (HMM_Vec2){ .x = -s + k.x * c,
.y = -k.y * s + c };
}

View File

@@ -12,8 +12,7 @@ struct sprite{
HMM_Vec2 scale;
float rotation;
HMM_Mat2 affine;
JSValue image; // the actual texture resource - perhaps SDL_GPUTexture, or SDL_Texture, or something else ...
rect uv; // pixel coordinates of the sprite on its image
JSValue image; // the JS image
int layer; // layer this sprite draws onto
HMM_Vec4 color; // color in 0-1f
};

View File

@@ -53,16 +53,13 @@ var bunny_count = 2000
for (var i = 0; i < bunny_count; i++) {
var pct = i/bunny_count
var sp = sprite.create(bunny, [Math.random()*dim.x*pct, Math.random()*dim.y*pct], center)
sp.dir = [Math.random()*vel, Math.random()*vel]
var hue = 270 * i / bunny_count
sp.color = hsl_to_rgb(hue, 0.5, 0.5)
}
function movendraw(sp)
{
sp.move([sp.dir[0]*dt, sp.dir[1]*dt])
// sp.draw()
var sp = sprite.create(bunny, {
pos: [Math.random()*dim.x*pct, Math.random()*dim.y*pct],
center,
color: hsl_to_rgb(hue, 0.5, 0.5)
})
sp.dir = [Math.random()*vel, Math.random()*vel]
}
var dt = 0
@@ -76,11 +73,15 @@ function loop()
render.clear([22/255,120/255,194/255,255/255])
render.camera(camera)
// sprite.forEach(movendraw)
sprite.forEach(x => x.move(x.dir.scale(dt)))
var queue = sprite.queue()
for (var q of queue)
//console.log(json.encode(queue))
for (var q of queue) {
if (!q.image) continue
render.geometry(q.image.texture, q.mesh)
}
render.present()
dt = os.now() - now

76
tests/qr_drag.js Normal file
View File

@@ -0,0 +1,76 @@
// bunnymark
var render = use('render')
var os = use('os')
var dim = [500,500]
render.initialize({
width:dim.x,
height:dim.y,
resolution_x:dim.x,
resolution_y:dim.y,
mode:"letterboxed",
refresh: 60,
})
var camera = {
size: [500,500],
transform: os.make_transform(),
fov:50,
near_z: 0,
far_z: 1000,
surface: undefined,
viewport: {x:0,y:0,width:1,height:1},
ortho:true,
anchor:[0,0],
}
var draw = use('draw2d')
var sprite = use('lcdsprite')
var graphics = use('graphics')
var dt = 0
var img = undefined
var ioguy = {
__ACTORDATA__: { id: os.ioactor() }
}
var io = use('io')
io.mount('/')
var qr = use('qr')
$_.send(ioguy, {
type: "subscribe",
actor: $_
})
$_.receiver(e => {
if (e.type === 'quit')
os.exit()
switch(e.type) {
case "drop_file":
console.log(`got ${e.data} dropped`)
img = e.data
var image = graphics.texture(e.data)
console.log(json.encode(qr.decode(image.surface.pixels(), image.surface.width(), image.surface.height(), image.surface.pitch())))
}
})
function loop()
{
var now = os.now()
render.clear([22/255,120/255,194/255,255/255])
render.camera(camera)
if (img)
draw.image(img, {x:0,y:0,width:300,height:300})
render.present()
dt = os.now() - now
var delay = (1/60) - dt
$_.delay(loop, delay)
}
loop()