text drawing
This commit is contained in:
183
.prosperon/imgui.ini
Normal file
183
.prosperon/imgui.ini
Normal file
@@ -0,0 +1,183 @@
|
||||
[Window][Debug##Default]
|
||||
Pos=60,60
|
||||
Size=400,400
|
||||
|
||||
[Window][TEST WINDOW]
|
||||
Pos=156,6
|
||||
Size=366,275
|
||||
|
||||
[Window][editor]
|
||||
Pos=558,248
|
||||
Size=274,177
|
||||
|
||||
[Window][Editor]
|
||||
Pos=-113,317
|
||||
Size=184,174
|
||||
|
||||
[Window][Map Editor]
|
||||
Pos=96,74
|
||||
Size=312,398
|
||||
|
||||
[Window][Edit Tile]
|
||||
Pos=120,99
|
||||
Size=356,275
|
||||
|
||||
[Window][Level Editor]
|
||||
Pos=60,45
|
||||
Size=283,332
|
||||
Collapsed=1
|
||||
|
||||
[Window][Brush Selector]
|
||||
Pos=189,35
|
||||
Size=203,474
|
||||
Collapsed=1
|
||||
|
||||
[Window][Tool Selector]
|
||||
Pos=300,25
|
||||
Size=247,474
|
||||
Collapsed=1
|
||||
|
||||
[Window][FPS: 12]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 87]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 59]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 107]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 135]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 136]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 140]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 137]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 138]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 141]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 143]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 142]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 144]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 139]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 133]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 134]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 131]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 130]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 128]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 126]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 123]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 124]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 121]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 122]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 119]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 117]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 118]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 116]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 108]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
|
||||
[Window][FPS: 109]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 115]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 114]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 113]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 110]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 112]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
[Window][FPS: 111]
|
||||
Pos=60,60
|
||||
Size=51,48
|
||||
|
||||
@@ -137,7 +137,7 @@ draw.slice9 = function slice9(image, rect = [0,0], slice = 0, info = slice9_info
|
||||
})
|
||||
}
|
||||
|
||||
draw.image = function image(image, rect, rotation, anchor, shear, info = {mode:"nearest"}, material) {
|
||||
draw.image = function image(image, rect, rotation, anchor, shear, info = {mode:"nearest"}, material = {color:{r:1,g:1,b:1,a:1}}) {
|
||||
if (!rect) throw Error('Need rectangle to render image.')
|
||||
if (!image) throw Error('Need an image to render.')
|
||||
|
||||
|
||||
@@ -212,14 +212,45 @@ function translate_draw_commands(commands) {
|
||||
case "draw_text":
|
||||
if (!cmd.text) break
|
||||
if (!cmd.pos) break
|
||||
var rect = worldToScreenRect({x:cmd.pos.x, y:cmd.pos.y, width:8, height:8}, camera)
|
||||
var pos = {x: rect.x, y: rect.y}
|
||||
renderer_commands.push({
|
||||
op: "debugText",
|
||||
data: {
|
||||
pos,
|
||||
text: cmd.text
|
||||
|
||||
// Get font from the font string (e.g., "smalle.16")
|
||||
var font = graphics.get_font(cmd.font, cmd.size)
|
||||
if (!font || !font.texture || !font.texture.id) break
|
||||
|
||||
// Create text geometry buffer
|
||||
var text_mesh = graphics.make_text_buffer(
|
||||
cmd.text,
|
||||
{x: cmd.pos.x, y: cmd.pos.y, width: 200, height: 50},
|
||||
cmd.size,
|
||||
[cmd.material.color.r, cmd.material.color.g, cmd.material.color.b, cmd.material.color.a],
|
||||
cmd.wrap || 0,
|
||||
font
|
||||
)
|
||||
|
||||
if (!text_mesh) break
|
||||
|
||||
// Transform XY coordinates using camera matrix
|
||||
var camera_params = [camera.a, camera.c, camera.e, camera.f]
|
||||
var transformed_xy = geometry.transform_xy_blob(text_mesh.xy, camera_params)
|
||||
|
||||
// Create transformed geometry object
|
||||
var transformed_geom = {
|
||||
xy: transformed_xy,
|
||||
xy_stride: text_mesh.xy_stride,
|
||||
uv: text_mesh.uv,
|
||||
uv_stride: text_mesh.uv_stride,
|
||||
color: text_mesh.color,
|
||||
color_stride: text_mesh.color_stride,
|
||||
indices: text_mesh.indices,
|
||||
num_vertices: text_mesh.num_vertices,
|
||||
num_indices: text_mesh.num_indices,
|
||||
size_indices: text_mesh.size_indices,
|
||||
texture_id: font.texture.id
|
||||
}
|
||||
|
||||
renderer_commands.push({
|
||||
op: "geometry_raw",
|
||||
data: transformed_geom
|
||||
})
|
||||
break
|
||||
|
||||
|
||||
@@ -98,6 +98,6 @@ function pump()
|
||||
$_.delay(pump, 1/240)
|
||||
}
|
||||
|
||||
pump()
|
||||
//pump()
|
||||
|
||||
return audio;
|
||||
|
||||
@@ -12,6 +12,7 @@ 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()
|
||||
@@ -412,7 +413,12 @@ graphics.get_font = function get_font(path, size) {
|
||||
if (fontcache[fontstr]) return fontcache[fontstr]
|
||||
|
||||
var data = io.slurpbytes(fullpath)
|
||||
var font = graphics.make_font(data,size)
|
||||
// Ensure size is a proper number
|
||||
var numericSize = Number(size)
|
||||
if (isNaN(numericSize) || numericSize <= 0) {
|
||||
numericSize = 16 // default size
|
||||
}
|
||||
var font = graphics.make_font(data, numericSize)
|
||||
|
||||
// Load font texture via renderer actor (async)
|
||||
if (renderer_actor) {
|
||||
|
||||
@@ -78,7 +78,6 @@ struct sFont *MakeFont(void *ttf_buffer, size_t len, int height) {
|
||||
quad.h = glyph.yoff2-glyph.yoff;
|
||||
newfont->Characters[c].quad = quad;
|
||||
newfont->Characters[c].advance = glyph.xadvance;
|
||||
// printf("glyph for %c is x0,y0,x1,y1: %d,%d,%d,%d\n xoff %g, yoff %g, xadvance %g, xoff2 %g, yoff2 %g\n", c, glyph.x0, glyph.y1, glyph.x1, glyph.y1, glyph.xoff, glyph.yoff, glyph.xadvance, glyph.xoff2, glyph.yoff2);
|
||||
}
|
||||
|
||||
free(bitmap);
|
||||
@@ -109,8 +108,8 @@ void draw_char_verts(struct text_vert **buffer, struct character c, HMM_Vec2 cur
|
||||
// packedchar has
|
||||
// Adds four verts: bottom left, bottom right, top left, top right
|
||||
text_vert bl;
|
||||
bl.pos.x = cursor.X + c.quad.x;
|
||||
bl.pos.y = cursor.Y + c.quad.y;
|
||||
bl.pos.x = cursor.X + c.quad.x * scale;
|
||||
bl.pos.y = cursor.Y + c.quad.y * scale;
|
||||
bl.uv.x = c.uv.x;
|
||||
bl.uv.y = c.uv.y;
|
||||
bl.color = color;
|
||||
@@ -118,12 +117,12 @@ void draw_char_verts(struct text_vert **buffer, struct character c, HMM_Vec2 cur
|
||||
|
||||
|
||||
text_vert br = bl;
|
||||
br.pos.x += c.quad.w;
|
||||
br.pos.x += c.quad.w * scale;
|
||||
br.uv.x += c.uv.w;
|
||||
arrput(*buffer, br);
|
||||
|
||||
text_vert ul = bl;
|
||||
ul.pos.y += c.quad.h;
|
||||
ul.pos.y += c.quad.h * scale;
|
||||
ul.uv.y += c.uv.h;
|
||||
arrput(*buffer, ul);
|
||||
|
||||
@@ -238,30 +237,32 @@ struct text_vert *renderText(const char *text, HMM_Vec2 pos, font *f, float scal
|
||||
text_vert *buffer = NULL;
|
||||
|
||||
HMM_Vec2 cursor = pos;
|
||||
float lineHeight = f->ascent - f->descent;
|
||||
float lineHeight = (f->ascent - f->descent) * scale;
|
||||
float lineWidth = 0;
|
||||
float scaledLinegap = f->linegap * scale;
|
||||
|
||||
for (const char *c = text; *c != 0; c++) {
|
||||
if (*c == '\n') {
|
||||
cursor.x = pos.x;
|
||||
cursor.y -= lineHeight + f->linegap;
|
||||
cursor.y -= lineHeight + scaledLinegap;
|
||||
lineWidth = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
struct character chara = f->Characters[(unsigned char)*c];
|
||||
float scaledAdvance = chara.advance * scale;
|
||||
|
||||
if (wrap > 0 && lineWidth + chara.advance > wrap) {
|
||||
if (wrap > 0 && lineWidth + scaledAdvance > wrap) {
|
||||
cursor.x = pos.x;
|
||||
cursor.y -= lineHeight + f->linegap;
|
||||
cursor.y -= lineHeight + scaledLinegap;
|
||||
lineWidth = 0;
|
||||
}
|
||||
|
||||
if (!isspace(*c))
|
||||
draw_char_verts(&buffer, chara, cursor, scale, color);
|
||||
|
||||
lineWidth += chara.advance;
|
||||
cursor.x += chara.advance;
|
||||
lineWidth += scaledAdvance;
|
||||
cursor.x += scaledAdvance;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
|
||||
@@ -296,31 +296,61 @@ JSValue quads_to_mesh(JSContext *js, text_vert *buffer)
|
||||
{
|
||||
size_t verts = arrlen(buffer);
|
||||
|
||||
HMM_Vec2 *pos = malloc(arrlen(buffer)*sizeof(HMM_Vec2));
|
||||
HMM_Vec2 *uv = malloc(arrlen(buffer)*sizeof(HMM_Vec2));
|
||||
HMM_Vec4 *color = malloc(arrlen(buffer)*sizeof(HMM_Vec4));
|
||||
// Allocate flat arrays for xy, uv, and color data
|
||||
size_t xy_size = verts * 2 * sizeof(float);
|
||||
size_t uv_size = verts * 2 * sizeof(float);
|
||||
size_t color_size = verts * sizeof(SDL_FColor);
|
||||
|
||||
for (int i = 0; i < arrlen(buffer); i++) {
|
||||
pos[i] = buffer[i].pos;
|
||||
uv[i] = buffer[i].uv;
|
||||
color[i] = buffer[i].color;
|
||||
float *xy_data = malloc(xy_size);
|
||||
float *uv_data = malloc(uv_size);
|
||||
SDL_FColor *color_data = malloc(color_size);
|
||||
|
||||
// Convert vertex data to flat arrays
|
||||
for (int i = 0; i < verts; i++) {
|
||||
xy_data[i*2] = buffer[i].pos.x;
|
||||
xy_data[i*2+1] = buffer[i].pos.y;
|
||||
|
||||
uv_data[i*2] = buffer[i].uv.x;
|
||||
uv_data[i*2+1] = buffer[i].uv.y;
|
||||
|
||||
color_data[i].r = buffer[i].color.x;
|
||||
color_data[i].g = buffer[i].color.y;
|
||||
color_data[i].b = buffer[i].color.z;
|
||||
color_data[i].a = buffer[i].color.w;
|
||||
}
|
||||
|
||||
JSValue jspos = make_gpu_buffer(js, pos, sizeof(HMM_Vec2)*arrlen(buffer), 0, 2,0,0);
|
||||
JSValue jsuv = make_gpu_buffer(js, uv, sizeof(HMM_Vec2)*arrlen(buffer), 0, 2,0,0);
|
||||
JSValue jscolor = make_gpu_buffer(js, color, sizeof(HMM_Vec4)*arrlen(buffer), 0, 4,0,0);
|
||||
|
||||
size_t quads = verts/4;
|
||||
size_t count = verts/2*3;
|
||||
JSValue jsidx = make_quad_indices_buffer(js, quads);
|
||||
size_t count = quads*6;
|
||||
|
||||
// Create indices
|
||||
uint16_t *indices = malloc(sizeof(uint16_t)*count);
|
||||
for (int i = 0, v = 0; i < count; i += 6, v += 4) {
|
||||
indices[i] = v;
|
||||
indices[i+1] = v+2;
|
||||
indices[i+2] = v+1;
|
||||
indices[i+3] = v+2;
|
||||
indices[i+4] = v+3;
|
||||
indices[i+5] = v+1;
|
||||
}
|
||||
|
||||
JSValue ret = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, ret, "pos", jspos);
|
||||
JS_SetPropertyStr(js, ret, "uv", jsuv);
|
||||
JS_SetPropertyStr(js, ret, "color", jscolor);
|
||||
JS_SetPropertyStr(js, ret, "indices", jsidx);
|
||||
JS_SetPropertyStr(js, ret, "vertices", number2js(js, verts));
|
||||
JS_SetPropertyStr(js,ret,"num_indices", number2js(js,count));
|
||||
|
||||
// Create blobs for geometry data
|
||||
JS_SetPropertyStr(js, ret, "xy", js_new_blob_stoned_copy(js, xy_data, xy_size));
|
||||
JS_SetPropertyStr(js, ret, "xy_stride", JS_NewInt32(js, 2 * sizeof(float)));
|
||||
JS_SetPropertyStr(js, ret, "uv", js_new_blob_stoned_copy(js, uv_data, uv_size));
|
||||
JS_SetPropertyStr(js, ret, "uv_stride", JS_NewInt32(js, 2 * sizeof(float)));
|
||||
JS_SetPropertyStr(js, ret, "color", js_new_blob_stoned_copy(js, color_data, color_size));
|
||||
JS_SetPropertyStr(js, ret, "color_stride", JS_NewInt32(js, sizeof(SDL_FColor)));
|
||||
JS_SetPropertyStr(js, ret, "indices", js_new_blob_stoned_copy(js, indices, sizeof(uint16_t)*count));
|
||||
JS_SetPropertyStr(js, ret, "num_vertices", JS_NewInt32(js, verts));
|
||||
JS_SetPropertyStr(js, ret, "num_indices", JS_NewInt32(js, count));
|
||||
JS_SetPropertyStr(js, ret, "size_indices", JS_NewInt32(js, 2)); // uint16_t size
|
||||
|
||||
free(xy_data);
|
||||
free(uv_data);
|
||||
free(color_data);
|
||||
free(indices);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -718,7 +748,8 @@ JSC_CCALL(os_make_text_buffer,
|
||||
colorf c = js2color(js,argv[3]);
|
||||
int wrap = js2number(js,argv[4]);
|
||||
HMM_Vec2 startpos = {.x = rectpos.x, .y = rectpos.y };
|
||||
text_vert *buffer = renderText(s, startpos, f, size, c, wrap);
|
||||
float scale = size / f->height;
|
||||
text_vert *buffer = renderText(s, startpos, f, scale, c, wrap);
|
||||
ret = quads_to_mesh(js,buffer);
|
||||
JS_FreeCString(js, s);
|
||||
arrfree(buffer);
|
||||
|
||||
Reference in New Issue
Block a user