clay
This commit is contained in:
parent
7f6996d93f
commit
2a1a5231aa
|
@ -873,6 +873,11 @@ render.rectangle = function render_rectangle(lowerleft, upperright, color, shade
|
||||||
check_flush(flush_poly);
|
check_flush(flush_poly);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
render.brect = function(brect, color = Color.white)
|
||||||
|
{
|
||||||
|
render.rectangle([brect.x,brect.y], [brect.x+brect.width, brect.y+brect.height], color);
|
||||||
|
}
|
||||||
|
|
||||||
render.rect = function(rect, color, shader, pipe)
|
render.rect = function(rect, color, shader, pipe)
|
||||||
{
|
{
|
||||||
render.rectangle([rect.x-rect.w/2, rect.y-rect.h/2], [rect.x+rect.w/2, rect.y+rect.h/2], color, shader, pipe);
|
render.rectangle([rect.x-rect.w/2, rect.y-rect.h/2], [rect.x+rect.w/2, rect.y+rect.h/2], color, shader, pipe);
|
||||||
|
@ -890,32 +895,11 @@ render.window = function render_window(pos, wh, color) {
|
||||||
render.box(pos.add(wh.scale(0.5)), wh, color);
|
render.box(pos.add(wh.scale(0.5)), wh, color);
|
||||||
};
|
};
|
||||||
|
|
||||||
render.text_bb = function (str, size = 1, wrap = -1, pos = [0, 0]) {
|
render.text = function (str, pos, font = cur_font, size = 1, color = Color.white, wrap = -1) {
|
||||||
var bb = render.text_size(str, size, wrap);
|
if (!font) return;
|
||||||
var w = bb.r - bb.l;
|
gui.text(str, pos, size, color, wrap, font); // this puts text into buffer
|
||||||
var h = bb.t - bb.b;
|
cur_font = font;
|
||||||
|
|
||||||
bb.r += pos.x;
|
|
||||||
bb.l += pos.x;
|
|
||||||
bb.t += pos.y;
|
|
||||||
bb.b += pos.y;
|
|
||||||
return bb;
|
|
||||||
};
|
|
||||||
|
|
||||||
render.text = function (str, pos, size = 1, color = Color.white, wrap = -1, anchor = [0, 1], cursor = -1) {
|
|
||||||
var bb = render.text_bb(str, size, wrap, pos);
|
|
||||||
gui.text(str, pos, size, color, wrap, cursor); // this puts text into buffer
|
|
||||||
check_flush(render.flush_text);
|
check_flush(render.flush_text);
|
||||||
return bb;
|
|
||||||
|
|
||||||
p.x -= w * anchor.x;
|
|
||||||
bb.r += w * anchor.x;
|
|
||||||
bb.l += w * anchor.x;
|
|
||||||
p.y += h * (1 - anchor.y);
|
|
||||||
bb.t += h * (1 - anchor.y);
|
|
||||||
bb.b += h * (1 - anchor.y);
|
|
||||||
|
|
||||||
return bb;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var lasttex = undefined;
|
var lasttex = undefined;
|
||||||
|
@ -1063,7 +1047,10 @@ render.image = function image(image, pos, scale, rotation = 0, color = Color.whi
|
||||||
};
|
};
|
||||||
|
|
||||||
// pos is the lower left corner, scale is the width and height
|
// pos is the lower left corner, scale is the width and height
|
||||||
render.slice9 = function (tex, pos, bb, scale = [tex.width, tex.height], color = Color.white) {
|
render.slice9 = function (image, pos, bb, scale = [tex.width, tex.height], color = Color.white) {
|
||||||
|
if (typeof image === 'string')
|
||||||
|
image = game.texture(image);
|
||||||
|
var tex = image.texture;
|
||||||
var t = os.make_transform();
|
var t = os.make_transform();
|
||||||
t.pos = pos;
|
t.pos = pos;
|
||||||
t.scale = [scale.x / tex.width, scale.y / tex.height, 1];
|
t.scale = [scale.x / tex.width, scale.y / tex.height, 1];
|
||||||
|
@ -1090,6 +1077,7 @@ function endframe() {
|
||||||
|
|
||||||
var textssbos = [];
|
var textssbos = [];
|
||||||
var tdraw = 0;
|
var tdraw = 0;
|
||||||
|
var cur_font = undefined;
|
||||||
|
|
||||||
render.flush_text = function () {
|
render.flush_text = function () {
|
||||||
if (!render.textshader) return;
|
if (!render.textshader) return;
|
||||||
|
@ -1105,22 +1093,18 @@ render.flush_text = function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
render.use_shader(render.textshader);
|
render.use_shader(render.textshader);
|
||||||
render.use_mat({ text: render.font.texture });
|
render.use_mat({ text: cur_font.texture });
|
||||||
|
|
||||||
render.draw(shape.quad, textssbo, amt);
|
render.draw(shape.quad, textssbo, amt);
|
||||||
};
|
};
|
||||||
|
|
||||||
var fontcache = {};
|
var fontcache = {};
|
||||||
render.set_font = function (path, size) {
|
|
||||||
|
render.get_font = function(path,size)
|
||||||
|
{
|
||||||
var fontstr = `${path}-${size}`;
|
var fontstr = `${path}-${size}`;
|
||||||
if (render.font && fontcache[fontstr] === render.font) return;
|
if (!fontcache[fontstr]) fontcache[fontstr] = os.make_font(path,size);
|
||||||
if (!fontcache[fontstr]) fontcache[fontstr] = os.make_font(path, size);
|
return fontcache[fontstr];
|
||||||
|
}
|
||||||
render.flush_text();
|
|
||||||
|
|
||||||
gui.font_set(fontcache[fontstr]);
|
|
||||||
render.font = fontcache[fontstr];
|
|
||||||
};
|
|
||||||
|
|
||||||
render.doc = "Draw shapes in screen space.";
|
render.doc = "Draw shapes in screen space.";
|
||||||
render.cross.doc = "Draw a cross centered at pos, with arm length size.";
|
render.cross.doc = "Draw a cross centered at pos, with arm length size.";
|
||||||
|
|
|
@ -269,7 +269,6 @@ Cmdline.register_order(
|
||||||
if (project.title) window.title = project.title;
|
if (project.title) window.title = project.title;
|
||||||
|
|
||||||
game.engine_start(function () {
|
game.engine_start(function () {
|
||||||
render.set_font("fonts/c64.ttf", 8);
|
|
||||||
if (io.exists("game.js")) global.app = actor.spawn("game.js");
|
if (io.exists("game.js")) global.app = actor.spawn("game.js");
|
||||||
else global.app = actor.spawn("scripts/nogame.js");
|
else global.app = actor.spawn("scripts/nogame.js");
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ struct letter {
|
||||||
vec2 pos;
|
vec2 pos;
|
||||||
vec2 wh;
|
vec2 wh;
|
||||||
vec2 uv;
|
vec2 uv;
|
||||||
vec2 st;
|
vec2 uv_size;
|
||||||
vec4 color;
|
vec4 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ readonly buffer ssbo {
|
||||||
letter ls[];
|
letter ls[];
|
||||||
};
|
};
|
||||||
|
|
||||||
out vec2 uv;
|
out vec2 uv; // Normalized UV, from 0 to 1 on the letter, for special effects
|
||||||
out vec2 fuv;
|
out vec2 fuv; // This is the UV given to get the correct letter from the texture
|
||||||
out vec4 color0;
|
out vec4 color0;
|
||||||
|
|
||||||
vec2 pos;
|
vec2 pos;
|
||||||
|
@ -26,11 +26,11 @@ uniform mat4 vp;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
letter l = ls[gl_InstanceIndex];
|
letter charData = ls[gl_InstanceIndex];
|
||||||
fuv = l.uv + vec2(a_pos.x*l.st.x, l.st.y - a_pos.y*l.st.y);
|
fuv = charData.uv + vec2(a_pos.x*charData.uv_size.x, charData.uv_size.y - a_pos.y*charData.uv_size.y);
|
||||||
uv = a_uv;
|
uv = a_uv;
|
||||||
color0 = l.color;
|
color0 = charData.color;
|
||||||
pos = l.pos+(a_pos*l.wh);
|
pos = charData.pos+(a_pos*charData.wh);
|
||||||
vert();
|
vert();
|
||||||
gl_Position = vp * vec4(pos, 0.0, 1.0);
|
gl_Position = vp * vec4(pos, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,6 +261,7 @@ typedef struct
|
||||||
uint16_t lineHeight;
|
uint16_t lineHeight;
|
||||||
Clay_TextElementConfigWrapMode wrapMode;
|
Clay_TextElementConfigWrapMode wrapMode;
|
||||||
struct sFont *font;
|
struct sFont *font;
|
||||||
|
JSValue jsstr;
|
||||||
#ifdef CLAY_EXTEND_CONFIG_ELEMENT
|
#ifdef CLAY_EXTEND_CONFIG_ELEMENT
|
||||||
CLAY_EXTEND_CONFIG_ELEMENT
|
CLAY_EXTEND_CONFIG_ELEMENT
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -36,11 +36,6 @@ void font_free(font *f)
|
||||||
free(f);
|
free(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void font_set(font *f)
|
|
||||||
{
|
|
||||||
use_font = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sFont *MakeSDFFont(const char *fontfile, int height)
|
struct sFont *MakeSDFFont(const char *fontfile, int height)
|
||||||
{
|
{
|
||||||
YughInfo("Making sdf font %s.", fontfile);
|
YughInfo("Making sdf font %s.", fontfile);
|
||||||
|
@ -99,10 +94,11 @@ struct sFont *MakeFont(const char *fontfile, int height) {
|
||||||
int ascent, descent, linegap;
|
int ascent, descent, linegap;
|
||||||
|
|
||||||
stbtt_GetFontVMetrics(&fontinfo, &ascent, &descent, &linegap);
|
stbtt_GetFontVMetrics(&fontinfo, &ascent, &descent, &linegap);
|
||||||
float emscale = tbtt_ScaleForMappingEmToPixels(&fontinfo, height);
|
float emscale = stbtt_ScaleForMappingEmToPixels(&fontinfo, height);
|
||||||
newfont->ascent = ascent*emscale;
|
newfont->ascent = ascent*emscale;
|
||||||
newfont->descent = descent*emscale;
|
newfont->descent = descent*emscale;
|
||||||
newfont->linegap = linegap*emscale;
|
newfont->linegap = linegap*emscale;
|
||||||
|
printf("ascent %g descent %g linegap %g\n", newfont->ascent, newfont->descent, newfont->linegap);
|
||||||
|
|
||||||
newfont->texture = malloc(sizeof(texture));
|
newfont->texture = malloc(sizeof(texture));
|
||||||
newfont->texture->id = sg_make_image(&(sg_image_desc){
|
newfont->texture->id = sg_make_image(&(sg_image_desc){
|
||||||
|
@ -129,6 +125,11 @@ struct sFont *MakeFont(const char *fontfile, int height) {
|
||||||
r.y = (glyph.y0) / (float)packsize;
|
r.y = (glyph.y0) / (float)packsize;
|
||||||
r.h = (glyph.y1-glyph.y0) / (float)packsize;
|
r.h = (glyph.y1-glyph.y0) / (float)packsize;
|
||||||
|
|
||||||
|
newfont->Characters[c].size = (HMM_Vec2){
|
||||||
|
.x = glyph.x1-glyph.x0,
|
||||||
|
.y = glyph.y1-glyph.y0
|
||||||
|
};
|
||||||
|
|
||||||
newfont->Characters[c].Advance = glyph.xadvance; /* x distance from this char to the next */
|
newfont->Characters[c].Advance = glyph.xadvance; /* x distance from this char to the next */
|
||||||
newfont->Characters[c].rect = r;
|
newfont->Characters[c].rect = r;
|
||||||
}
|
}
|
||||||
|
@ -139,27 +140,6 @@ struct sFont *MakeFont(const char *fontfile, int height) {
|
||||||
return newfont;
|
return newfont;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_underline_cursor(HMM_Vec2 pos, float scale, struct rgba color)
|
|
||||||
{
|
|
||||||
pos.Y -= 2;
|
|
||||||
sdrawCharacter(use_font->Characters['_'], pos, scale, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_char_box(struct Character c, HMM_Vec2 cursor, float scale, struct rgba color)
|
|
||||||
{
|
|
||||||
HMM_Vec2 wh;
|
|
||||||
color.a = 30;
|
|
||||||
|
|
||||||
wh.x = c.Size[0] * scale + 2;
|
|
||||||
wh.y = c.Size[1] * scale + 2;
|
|
||||||
cursor.X += c.Bearing[0] * scale + 1;
|
|
||||||
cursor.Y -= (c.Bearing[1] * scale + 1);
|
|
||||||
|
|
||||||
HMM_Vec2 b;
|
|
||||||
b.x = cursor.X + wh.x/2;
|
|
||||||
b.y = cursor.Y + wh.y/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int text_flush(sg_buffer *buf) {
|
int text_flush(sg_buffer *buf) {
|
||||||
if (arrlen(text_buffer) == 0) return 0;
|
if (arrlen(text_buffer) == 0) return 0;
|
||||||
|
|
||||||
|
@ -183,14 +163,11 @@ int text_flush(sg_buffer *buf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgba color) {
|
void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgba color) {
|
||||||
struct rgba colorbox = {0,0,0,255};
|
|
||||||
|
|
||||||
struct text_vert vert;
|
struct text_vert vert;
|
||||||
|
|
||||||
vert.pos.x = cursor.X + c.Bearing[0] * scale;
|
vert.pos.x = cursor.X + c.leftbearing * scale;
|
||||||
vert.pos.y = cursor.Y - c.Bearing[1] * scale;
|
vert.pos.y = cursor.Y - c.topbearing * scale;
|
||||||
vert.wh.x = c.\Size[0] * scale;
|
vert.wh = c.size;
|
||||||
vert.wh.y = c.Size[1] * scale;
|
|
||||||
|
|
||||||
// if (vert.pos.x > frame.l || vert.pos.y > frame.t || (vert.pos.y + vert.wh.y) < frame.b || (vert.pos.x + vert.wh.x) < frame.l) return;
|
// if (vert.pos.x > frame.l || vert.pos.y > frame.t || (vert.pos.y + vert.wh.y) < frame.b || (vert.pos.x + vert.wh.x) < frame.l) return;
|
||||||
|
|
||||||
|
@ -230,92 +207,71 @@ const char *esc_color(const char *c, struct rgba *color, struct rgba defc)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct boundingbox text_bb(const char *text, float scale, float lw, float tracking)
|
// text is a string, font f, size is height in pixels, wrap is how long a line is before wrapping. -1to not wrap
|
||||||
|
HMM_Vec2 measure_text(const char *text, font *f, float size, float letterSpacing, float wrap)
|
||||||
{
|
{
|
||||||
if (!use_font) return cwh2bb((HMM_Vec2){0,0}, (HMM_Vec2){0,0});
|
HMM_Vec2 dim = {0};
|
||||||
struct rgba dummy;
|
float maxWidth = 0; // max width of any line
|
||||||
HMM_Vec2 cursor = {0,0};
|
float lineWidth = 0; // current line width
|
||||||
const char *line, *wordstart;
|
size = f->height;
|
||||||
line = text;
|
|
||||||
|
|
||||||
while (*line != '\0') {
|
float scale = size/f->height;
|
||||||
if (isblank(*line)) {
|
float lineHeight = f->ascent - f->descent;
|
||||||
cursor.X += use_font->Characters[*line].Advance * tracking * scale;
|
lineHeight *= scale;
|
||||||
line++;
|
letterSpacing *= scale;
|
||||||
} else if (isspace(*line)) {
|
|
||||||
cursor.Y -= scale * use_font->linegap;
|
|
||||||
cursor.X = 0;
|
|
||||||
line++;
|
|
||||||
} else {
|
|
||||||
if (*line == '\e')
|
|
||||||
line = esc_color(line, NULL, dummy);
|
|
||||||
|
|
||||||
wordstart = line;
|
float height = lineHeight; // total height
|
||||||
int wordWidth = 0;
|
|
||||||
|
|
||||||
while (!isspace(*line) && *line != '\0') {
|
for (char *c = text; *c != 0; c++) {
|
||||||
wordWidth += use_font->Characters[*line].Advance * tracking * scale;
|
if (*c == '\n') {
|
||||||
line++;
|
maxWidth = fmaxf(maxWidth, lineWidth);
|
||||||
|
lineWidth = 0;
|
||||||
|
height += lineHeight + f->linegap;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
lineWidth += f->Characters[*c].Advance + letterSpacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lw > 0 && (cursor.X + wordWidth) >= lw) {
|
maxWidth = fmaxf(maxWidth, lineWidth);
|
||||||
cursor.X = 0;
|
dim.x = maxWidth;
|
||||||
cursor.Y -= scale * use_font->linegap;
|
dim.y = height;
|
||||||
}
|
return dim;
|
||||||
|
|
||||||
while (wordstart < line) {
|
|
||||||
if (*wordstart == '\e')
|
|
||||||
line = esc_color(wordstart, NULL, dummy);
|
|
||||||
|
|
||||||
cursor.X += use_font->Characters[*wordstart].Advance * tracking * scale;
|
|
||||||
wordstart++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (struct boundingbox){
|
|
||||||
.b = cursor.Y + use_font->descent,
|
|
||||||
.t = cursor.Y + use_font->ascent,
|
|
||||||
.l = 0,
|
|
||||||
.r = cursor.X
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_caret(int caret, int l, HMM_Vec2 pos, float scale, struct rgba color)
|
|
||||||
{
|
|
||||||
if (caret == l)
|
|
||||||
draw_underline_cursor(pos,scale,color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pos given in screen coordinates */
|
/* pos given in screen coordinates */
|
||||||
int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, float lw, int caret, float tracking) {
|
void renderText(const char *text, HMM_Vec2 pos, font *f, float scale, struct rgba color, float wrap) {
|
||||||
if (!use_font) {
|
|
||||||
YughError("Cannot render text before a font is set.");
|
|
||||||
return pos.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
int len = strlen(text);
|
int len = strlen(text);
|
||||||
|
|
||||||
HMM_Vec2 cursor = pos;
|
HMM_Vec2 cursor = pos;
|
||||||
|
float lineHeight = f->ascent - f->descent;
|
||||||
|
|
||||||
|
for (char *c = text; *c != 0; c++) {
|
||||||
|
if (*c == '\n') {
|
||||||
|
cursor.x = pos.x;
|
||||||
|
cursor.y += lineHeight + f->linegap;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdrawCharacter(f->Characters[*c], cursor, scale, color);
|
||||||
|
cursor.x += f->Characters[*c].Advance;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
const char *line, *wordstart, *drawstart;
|
const char *line, *wordstart, *drawstart;
|
||||||
line = drawstart = text;
|
line = drawstart = text;
|
||||||
|
|
||||||
struct rgba usecolor = color;
|
struct rgba usecolor = color;
|
||||||
check_caret(caret, line-drawstart, cursor, scale, usecolor);
|
|
||||||
|
|
||||||
while (*line != '\0') {
|
while (*line != '\0') {
|
||||||
if (isblank(*line)) {
|
if (isblank(*line)) {
|
||||||
sdrawCharacter(use_font->Characters[*line], cursor, scale, usecolor);
|
sdrawCharacter(f->Characters[*line], cursor, scale, usecolor);
|
||||||
cursor.X += use_font->Characters[*line].Advance * tracking * scale;
|
cursor.X += f->Characters[*line].Advance * scale;
|
||||||
line++;
|
line++;
|
||||||
check_caret(caret, line-drawstart, cursor, scale, usecolor);
|
|
||||||
} else if (isspace(*line)) {
|
} else if (isspace(*line)) {
|
||||||
sdrawCharacter(use_font->Characters[*line], cursor, scale, usecolor);
|
sdrawCharacter(f->Characters[*line], cursor, scale, usecolor);
|
||||||
cursor.Y -= scale * use_font->linegap;
|
cursor.Y -= scale * f->linegap;
|
||||||
cursor.X = pos.X;
|
cursor.X = pos.X;
|
||||||
line++;
|
line++;
|
||||||
check_caret(caret, line-drawstart, cursor, scale, usecolor);
|
|
||||||
} else {
|
} else {
|
||||||
if (*line == '\e')
|
if (*line == '\e')
|
||||||
line = esc_color(line, &usecolor, color);
|
line = esc_color(line, &usecolor, color);
|
||||||
|
@ -325,28 +281,25 @@ int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, f
|
||||||
|
|
||||||
while (!isspace(*line) && *line != '\0') {
|
while (!isspace(*line) && *line != '\0') {
|
||||||
|
|
||||||
wordWidth += use_font->Characters[*line].Advance * tracking * scale;
|
wordWidth += f->Characters[*line].Advance * scale;
|
||||||
line++;
|
line++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lw > 0 && (cursor.X + wordWidth - pos.X) >= lw) {
|
if (wrap > 0 && (cursor.X + wordWidth - pos.X) >= wrap) {
|
||||||
cursor.X = pos.X;
|
cursor.X = pos.X;
|
||||||
cursor.Y -= scale * use_font->linegap;
|
cursor.Y -= scale * f->linegap;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (wordstart < line) {
|
while (wordstart < line) {
|
||||||
if (*wordstart == '\e')
|
if (*wordstart == '\e')
|
||||||
wordstart = esc_color(wordstart, &usecolor, color);
|
wordstart = esc_color(wordstart, &usecolor, color);
|
||||||
|
|
||||||
//sdrawCharacter(use_font->Characters[*wordstart], HMM_AddV2(cursor, HMM_MulV2F((HMM_Vec2){1,-1},scale)), scale, (rgba){0,0,0,255});
|
//sdrawCharacter(f->Characters[*wordstart], HMM_AddV2(cursor, HMM_MulV2F((HMM_Vec2){1,-1},scale)), scale, (rgba){0,0,0,255});
|
||||||
sdrawCharacter(use_font->Characters[*wordstart], cursor, scale, usecolor);
|
sdrawCharacter(f->Characters[*wordstart], cursor, scale, usecolor);
|
||||||
|
|
||||||
cursor.X += use_font->Characters[*wordstart].Advance * tracking * scale;
|
cursor.X += f->Characters[*wordstart].Advance * scale;
|
||||||
wordstart++;
|
wordstart++;
|
||||||
check_caret(caret, wordstart-drawstart, cursor, scale, usecolor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cursor.Y - pos.Y;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,11 @@ extern sg_buffer text_ssbo;
|
||||||
|
|
||||||
/// Holds all state information relevant to a character as loaded using FreeType
|
/// Holds all state information relevant to a character as loaded using FreeType
|
||||||
struct Character {
|
struct Character {
|
||||||
int Advance; // Horizontal offset to advance to next glyph
|
float Advance; // Horizontal offset to advance to next glyph
|
||||||
float leftbearing; // X offset from cursor to render at
|
float leftbearing; // X offset from cursor to render at
|
||||||
float topbearing; // Y offset from cursor to render at
|
float topbearing; // Y offset from cursor to render at
|
||||||
struct rect rect; // the rect on the font image to render from
|
struct rect rect; // the rect on the font image to render from, uv coordinates
|
||||||
|
HMM_Vec2 size; // The pixel size of this letter
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sFont {
|
struct sFont {
|
||||||
|
@ -29,16 +30,16 @@ struct sFont {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct sFont font;
|
typedef struct sFont font;
|
||||||
|
typedef struct Character glyph;
|
||||||
|
|
||||||
void font_free(font *f);
|
void font_free(font *f);
|
||||||
|
|
||||||
struct sFont *MakeFont(const char *fontfile, int height);
|
struct sFont *MakeFont(const char *fontfile, int height);
|
||||||
void font_set(font *f);
|
|
||||||
void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgba color);
|
void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgba color);
|
||||||
void text_settype(struct sFont *font);
|
void renderText(const char *text, HMM_Vec2 pos, font *f, float scale, struct rgba color, float wrap);
|
||||||
struct boundingbox text_bb(const char *text, float scale, float lw, float tracking);
|
HMM_Vec2 measure_text(const char *text, font *f, float scale, float letterSpacing, float wrap);
|
||||||
int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, float lw, int caret, float tracking);
|
|
||||||
|
|
||||||
|
// Flushes all letters from renderText calls into the provided buffer
|
||||||
int text_flush(sg_buffer *buf);
|
int text_flush(sg_buffer *buf);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -788,7 +788,9 @@ JSC_CCALL(render_viewport,
|
||||||
JSC_CCALL(render_commit, sg_commit())
|
JSC_CCALL(render_commit, sg_commit())
|
||||||
JSC_CCALL(render_end_pass, sg_end_pass())
|
JSC_CCALL(render_end_pass, sg_end_pass())
|
||||||
|
|
||||||
JSC_SCALL(render_text_size, ret = bb2js(text_bb(str, js2number(argv[1]), js2number(argv[2]), 1)))
|
JSC_SCALL(render_measure_text,
|
||||||
|
ret = vec22js(measure_text(str, js2font(argv[1]), js2number(argv[2]), js2number(argv[3]), js2number(argv[4])))
|
||||||
|
)
|
||||||
|
|
||||||
HMM_Mat4 transform2view(transform *t)
|
HMM_Mat4 transform2view(transform *t)
|
||||||
{
|
{
|
||||||
|
@ -1263,7 +1265,7 @@ static const JSCFunctionListEntry js_render_funcs[] = {
|
||||||
MIST_FUNC_DEF(render, end_pass, 0),
|
MIST_FUNC_DEF(render, end_pass, 0),
|
||||||
MIST_FUNC_DEF(render, commit, 0),
|
MIST_FUNC_DEF(render, commit, 0),
|
||||||
MIST_FUNC_DEF(render, glue_pass, 0),
|
MIST_FUNC_DEF(render, glue_pass, 0),
|
||||||
MIST_FUNC_DEF(render, text_size, 3),
|
MIST_FUNC_DEF(render, measure_text, 5),
|
||||||
MIST_FUNC_DEF(render, set_camera, 1),
|
MIST_FUNC_DEF(render, set_camera, 1),
|
||||||
MIST_FUNC_DEF(render, make_pipeline, 1),
|
MIST_FUNC_DEF(render, make_pipeline, 1),
|
||||||
MIST_FUNC_DEF(render, setuniv3, 2),
|
MIST_FUNC_DEF(render, setuniv3, 2),
|
||||||
|
@ -1387,25 +1389,18 @@ JSC_CCALL(gui_scissor,
|
||||||
sg_apply_scissor_rect(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0);
|
sg_apply_scissor_rect(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0);
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(gui_text,
|
JSC_SCALL(gui_text,
|
||||||
const char *s = JS_ToCString(js, argv[0]);
|
|
||||||
HMM_Vec2 pos = js2vec2(argv[1]);
|
HMM_Vec2 pos = js2vec2(argv[1]);
|
||||||
|
|
||||||
float size = js2number(argv[2]);
|
float size = js2number(argv[2]);
|
||||||
struct rgba c = js2color(argv[3]);
|
struct rgba c = js2color(argv[3]);
|
||||||
int wrap = js2number(argv[4]);
|
int wrap = js2number(argv[4]);
|
||||||
int cursor = js2number(argv[5]);
|
font *f = js2font(argv[5]);
|
||||||
JSValue ret = JS_NewInt64(js, renderText(s, pos, size, c, wrap, cursor, 1.0));
|
renderText(str, pos, f, size, c, wrap);
|
||||||
JS_FreeCString(js, s);
|
|
||||||
return ret;
|
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(gui_font_set, font_set(js2font(argv[0])))
|
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_gui_funcs[] = {
|
static const JSCFunctionListEntry js_gui_funcs[] = {
|
||||||
MIST_FUNC_DEF(gui, scissor, 4),
|
MIST_FUNC_DEF(gui, scissor, 4),
|
||||||
MIST_FUNC_DEF(gui, text, 6),
|
MIST_FUNC_DEF(gui, text, 6),
|
||||||
MIST_FUNC_DEF(gui, font_set,1)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JSC_CCALL(spline_catmull,
|
JSC_CCALL(spline_catmull,
|
||||||
|
@ -3818,15 +3813,18 @@ JSC_CCALL(clay_dimensions,
|
||||||
Clay_SetLayoutDimensions((Clay_Dimensions) { dim.x, dim.y });
|
Clay_SetLayoutDimensions((Clay_Dimensions) { dim.x, dim.y });
|
||||||
)
|
)
|
||||||
|
|
||||||
|
static int container_id = 0;
|
||||||
|
|
||||||
JSC_CCALL(clay_draw,
|
JSC_CCALL(clay_draw,
|
||||||
|
container_id = 0;
|
||||||
Clay_BeginLayout();
|
Clay_BeginLayout();
|
||||||
script_call_sym(argv[0], 0, NULL);
|
script_call_sym(argv[0], 0, NULL);
|
||||||
Clay_RenderCommandArray cmd = Clay_EndLayout();
|
Clay_RenderCommandArray cmd = Clay_EndLayout();
|
||||||
|
|
||||||
ret = JS_NewArray(js);
|
ret = JS_NewArray(js);
|
||||||
printf("there are %d commands here\n", cmd.length);
|
|
||||||
for (int i = 0; i < cmd.length; i++) {
|
for (int i = 0; i < cmd.length; i++) {
|
||||||
Clay_RenderCommand cc = cmd.internalArray[i];
|
Clay_RenderCommand cc = cmd.internalArray[i];
|
||||||
|
if (cc.commandType == CLAY_RENDER_COMMAND_TYPE_NONE) continue;
|
||||||
JSValue c = JS_NewObject(js);
|
JSValue c = JS_NewObject(js);
|
||||||
JSValue bb = JS_NewObject(js);
|
JSValue bb = JS_NewObject(js);
|
||||||
js_setpropstr(bb, "x", number2js(cc.boundingBox.x));
|
js_setpropstr(bb, "x", number2js(cc.boundingBox.x));
|
||||||
|
@ -3835,8 +3833,28 @@ JSC_CCALL(clay_draw,
|
||||||
js_setpropstr(bb, "height", number2js(cc.boundingBox.height));
|
js_setpropstr(bb, "height", number2js(cc.boundingBox.height));
|
||||||
js_setpropstr(c, "boundingbox", bb);
|
js_setpropstr(c, "boundingbox", bb);
|
||||||
js_setprop_num(ret, i, c);
|
js_setprop_num(ret, i, c);
|
||||||
|
|
||||||
|
switch(cc.commandType) {
|
||||||
|
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE:
|
||||||
Clay_RectangleElementConfig *rect = cc.config.rectangleElementConfig;
|
Clay_RectangleElementConfig *rect = cc.config.rectangleElementConfig;
|
||||||
js_setpropstr(c, "config", rect->js);
|
js_setpropstr(c, "config", JS_DupValue(js,rect->js));
|
||||||
|
break;
|
||||||
|
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_START:
|
||||||
|
js_setpropstr(c, "config", str2js("scissor_start"));
|
||||||
|
break;
|
||||||
|
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_END:
|
||||||
|
js_setpropstr(c, "config", str2js('scissor_end'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < cmd.length; i++) {
|
||||||
|
Clay_RenderCommand cc = cmd.internalArray[i];
|
||||||
|
if (cc.commandType != CLAY_RENDER_COMMAND_TYPE_RECTANGLE) continue;
|
||||||
|
Clay_RectangleElementConfig *rect = cc.config.rectangleElementConfig;
|
||||||
|
if (!JS_IsUndefined(rect->js)) {
|
||||||
|
JS_FreeValue(js, rect->js);
|
||||||
|
rect->js = JS_UNDEFINED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -3853,41 +3871,15 @@ JSC_CCALL(clay_updatescroll,
|
||||||
Clay_UpdateScrollContainers(drag, (Clay_Vector2){delta.x,delta.y}, dt);
|
Clay_UpdateScrollContainers(drag, (Clay_Vector2){delta.x,delta.y}, dt);
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_SCALL(clay_container,
|
JSC_CCALL(clay_container,
|
||||||
Clay_LayoutConfig config = js2layout(argv[1]);
|
Clay_LayoutConfig config = js2layout(argv[0]);
|
||||||
Clay_RectangleElementConfig rect = {0};
|
Clay_RectangleElementConfig rect = {0};
|
||||||
rect.js = JS_DupValue(js, argv[1]);
|
rect.js = JS_DupValue(js, argv[0]);
|
||||||
Clay_String cstr;
|
Clay__OpenRectangleElement(CLAY_IDI_LOCAL("container", container_id++), &config, &rect);
|
||||||
cstr.length = strlen(str);
|
script_call_sym(argv[1], 0, NULL);
|
||||||
cstr.chars = str;
|
|
||||||
// Clay__OpenRectangleElement(Clay__HashString(cstr,0,0), &config, &rect);
|
|
||||||
Clay__OpenRectangleElement(CLAY_ID("TEST"), &config, &rect);
|
|
||||||
script_call_sym(argv[2], 0, NULL);
|
|
||||||
Clay__CloseElementWithChildren();
|
Clay__CloseElementWithChildren();
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_SCALL(clay_image,
|
|
||||||
Clay_LayoutConfig config = js2layout(argv[1]);
|
|
||||||
Clay_ImageElementConfig image = {0};
|
|
||||||
HMM_Vec2 dim = js2vec2(argv[2]);
|
|
||||||
image.sourceDimensions.width = dim.x;
|
|
||||||
image.sourceDimensions.height = dim.y;
|
|
||||||
Clay__OpenImageElement(CLAY_ID(str), &config, &image);
|
|
||||||
script_call_sym(argv[3], 0, NULL);
|
|
||||||
Clay__CloseElementWithChildren();
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_SSCALL(clay_text,
|
|
||||||
Clay_TextElementConfig text = {0};
|
|
||||||
text.fontSize = js2number(js_getpropstr(argv[2], "font_size"));
|
|
||||||
text.letterSpacing = js2number(js_getpropstr(argv[2], "letter_spacing"));
|
|
||||||
text.lineHeight = js2number(js_getpropstr(argv[2], "line_spacing"));
|
|
||||||
text.wrapMode = (Clay_TextElementConfigWrapMode)js2number(js_getpropstr(argv[2], "wrap"));
|
|
||||||
text.font = js2font(js_getpropstr(argv[2], "font"));
|
|
||||||
Clay__OpenTextElement(CLAY_ID(str), CLAY_STRING(str2), &text);
|
|
||||||
// CLAY_TEXT(CLAY_ID(str), CLAY_STRING(str2), text)
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_SCALL(clay_scroll,
|
JSC_SCALL(clay_scroll,
|
||||||
Clay_LayoutConfig config = js2layout(argv[1]);
|
Clay_LayoutConfig config = js2layout(argv[1]);
|
||||||
Clay_ScrollElementConfig scroll = {0};
|
Clay_ScrollElementConfig scroll = {0};
|
||||||
|
@ -3926,32 +3918,11 @@ static const JSCFunctionListEntry js_clay_funcs[] = {
|
||||||
MIST_FUNC_DEF(clay, draw, 1),
|
MIST_FUNC_DEF(clay, draw, 1),
|
||||||
MIST_FUNC_DEF(clay, pointer, 2),
|
MIST_FUNC_DEF(clay, pointer, 2),
|
||||||
MIST_FUNC_DEF(clay, updatescroll, 3),
|
MIST_FUNC_DEF(clay, updatescroll, 3),
|
||||||
MIST_FUNC_DEF(clay, container, 3),
|
MIST_FUNC_DEF(clay, container, 2),
|
||||||
MIST_FUNC_DEF(clay, image, 4),
|
|
||||||
MIST_FUNC_DEF(clay, text, 3),
|
|
||||||
MIST_FUNC_DEF(clay, scroll, 3),
|
MIST_FUNC_DEF(clay, scroll, 3),
|
||||||
MIST_FUNC_DEF(clay, floating, 3),
|
MIST_FUNC_DEF(clay, floating, 3),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Example measure text function
|
|
||||||
static inline Clay_Dimensions MeasureText(Clay_String *text, Clay_TextElementConfig *config) {
|
|
||||||
// Clay_TextElementConfig contains members such as fontId, fontSize, letterSpacing etc
|
|
||||||
// Note: Clay_String->chars is not guaranteed to be null terminated
|
|
||||||
Clay_Dimensions size = {0};
|
|
||||||
float maxWidth = 0;
|
|
||||||
float lineWidth = 0;
|
|
||||||
|
|
||||||
float height = config->font->height;
|
|
||||||
float scale = config->fontSize/height;
|
|
||||||
float lineHeight = config->font->ascent + config->font->descent + config->font->linegap;
|
|
||||||
lineHeight *= config->lineHeight * scale;
|
|
||||||
float letterSpacing = config->letterSpacing * scale;
|
|
||||||
|
|
||||||
for (int i = 0; i < text->length; i++) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "steam.h"
|
#include "steam.h"
|
||||||
|
|
||||||
#define JSSTATIC(NAME, PARENT) \
|
#define JSSTATIC(NAME, PARENT) \
|
||||||
|
@ -4006,7 +3977,6 @@ void ffi_load() {
|
||||||
uint64_t totalMemorySize = Clay_MinMemorySize();
|
uint64_t totalMemorySize = Clay_MinMemorySize();
|
||||||
Clay_Arena arena = Clay_CreateArenaWithCapacityAndMemory(totalMemorySize, malloc(totalMemorySize));
|
Clay_Arena arena = Clay_CreateArenaWithCapacityAndMemory(totalMemorySize, malloc(totalMemorySize));
|
||||||
Clay_Initialize(arena, (Clay_Dimensions) { 1920, 1080 });
|
Clay_Initialize(arena, (Clay_Dimensions) { 1920, 1080 });
|
||||||
Clay_SetMeasureTextFunction(MeasureText);
|
|
||||||
QJSGLOBALCLASS(clay);
|
QJSGLOBALCLASS(clay);
|
||||||
|
|
||||||
QJSGLOBALCLASS(poly2d);
|
QJSGLOBALCLASS(poly2d);
|
||||||
|
|
Loading…
Reference in a new issue