fonts managed by javascript
This commit is contained in:
parent
5051d11005
commit
941106ced5
|
@ -357,10 +357,8 @@ var editor = {
|
|||
|
||||
this._sel_comp = x;
|
||||
|
||||
if (this._sel_comp) {
|
||||
console.info("sel comp is now " + this._sel_comp);
|
||||
if (this._sel_comp)
|
||||
player[0].control(this._sel_comp);
|
||||
}
|
||||
},
|
||||
|
||||
time: 0,
|
||||
|
@ -399,7 +397,7 @@ var editor = {
|
|||
render.text([0,0], game.camera.world2view([0,0]));
|
||||
|
||||
render.text("WORKING LAYER: " + this.working_layer, [0,520]);
|
||||
render.text("MODE: " + this.edit_mode, [0,500]);
|
||||
render.text("MODE: " + this.edit_mode, [0,520-render.font.linegap]);
|
||||
|
||||
if (this.comp_info && this.sel_comp)
|
||||
render.text(input.print_pawn_kbm(this.sel_comp,false), [100,700],1);
|
||||
|
@ -440,23 +438,23 @@ var editor = {
|
|||
var lvlstr = x.namestr();
|
||||
if (i === lvlchain.length-1) lvlstr += "[this]";
|
||||
render.text(lvlstr, [0, ypos], 1, editor.color_depths[depth]);
|
||||
|
||||
render.text("^^^^^^", [0,ypos+=5],1);
|
||||
ypos += 15;
|
||||
ypos += render.font.linegap;
|
||||
render.text("^^^^^^", [0,ypos],1);
|
||||
ypos += render.font.linegap;
|
||||
});
|
||||
|
||||
depth++;
|
||||
render.text("$$$$$$", [0,ypos],1,editor.color_depths[depth]);
|
||||
|
||||
this.selectlist.forEach(function(x) {
|
||||
render.text(x.urstr(), x.screenpos().add([0, 32]), 1, Color.editor.ur);
|
||||
render.text(x.pos.map(function(x) { return Math.round(x); }), x.screenpos(), 1, Color.white);
|
||||
render.text(x.urstr(), x.screenpos().add([0, render.font.linegap*2]), 1, Color.editor.ur);
|
||||
render.text(x.pos.map(function(x) { return Math.round(x); }), x.screenpos());
|
||||
render.cross(x.screenpos(), 10, Color.blue);
|
||||
});
|
||||
|
||||
Object.entries(thiso.objects).forEach(function(x) {
|
||||
var p = x[1].namestr();
|
||||
render.text(p, x[1].screenpos().add([0,16]),1,editor.color_depths[depth]);
|
||||
render.text(p, x[1].screenpos().add([0,render.font.linegap]),1,editor.color_depths[depth]);
|
||||
render.point(x[1].screenpos(),5,Color.blue.alpha(0.3));
|
||||
render.point(x[1].screenpos(), 1, Color.red);
|
||||
});
|
||||
|
@ -476,7 +474,7 @@ var editor = {
|
|||
for (var key in this.selectlist[0].components) {
|
||||
var selected = this.sel_comp === this.selectlist[0].components[key];
|
||||
var str = (selected ? ">" : " ") + key + " [" + this.selectlist[0].components[key].toString() + "]";
|
||||
render.text(str, this.selectlist[0].screenpos().add([0,-16*(i++)]));
|
||||
render.text(str, this.selectlist[0].screenpos().add([0,-render.font.linegap*(i++)]));
|
||||
}
|
||||
|
||||
if (this.sel_comp) {
|
||||
|
@ -692,9 +690,9 @@ editor.inputs.n = function() {
|
|||
if (o === editor.selectlist[0]) return;
|
||||
if (o.master !== editor.selectlist[0].master) return;
|
||||
|
||||
var tpos = editor.selectlist[0].pos;
|
||||
var tpos = editor.selectlist[0].get_pos(editor.selectlist[0].master);
|
||||
tpos.x *= -1;
|
||||
o.pos = tpos;
|
||||
o.set_pos(tpos, o.master);
|
||||
};
|
||||
editor.inputs.n.doc = "Set the hovered object's position to mirror the selected object's position on the X axis."
|
||||
editor.inputs['M-n'] = function()
|
||||
|
@ -743,7 +741,6 @@ editor.inputs['C-d'] = function() {
|
|||
};
|
||||
editor.inputs['C-d'].doc = "Duplicate all selected objects.";
|
||||
|
||||
|
||||
editor.inputs['C-m'] = function() {
|
||||
if (editor.sel_comp) {
|
||||
if ('flipy' in editor.sel_comp)
|
||||
|
@ -969,6 +966,10 @@ editor.inputs['C-y'] = function() {
|
|||
};
|
||||
editor.inputs['C-y'].doc = "Open script editor for the level.";
|
||||
|
||||
editor.inputs['C-p'] = function() {
|
||||
os.system("prosperon");
|
||||
}
|
||||
|
||||
editor.inputs['M-y'] = function() { editor.programmode = !editor.programmode; };
|
||||
editor.inputs['M-y'].doc = "Toggle program mode.";
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ var gameobject = {
|
|||
get scale() { return this.rscale; },
|
||||
|
||||
set_pos(x, relative = world) {
|
||||
var newpos = x.add(relative.pos);
|
||||
var newpos = relative.this2world(x);
|
||||
var move = newpos.sub(this.pos);
|
||||
this.rpos = newpos;
|
||||
this.objects.forEach(x => x.move(move));
|
||||
|
@ -181,7 +181,8 @@ var gameobject = {
|
|||
|
||||
get_pos(relative = world) {
|
||||
if (relative === world) return this.pos;
|
||||
return this.pos.sub(relative.pos);
|
||||
return relative.world2this(this.pos);
|
||||
//return this.pos.sub(relative.pos);
|
||||
},
|
||||
|
||||
get_angle(relative = world) {
|
||||
|
@ -325,15 +326,14 @@ var gameobject = {
|
|||
|
||||
parent.objects[name] = this;
|
||||
parent[name] = this;
|
||||
Object.hide(parent, name);
|
||||
this.toString = function() { return name; };
|
||||
},
|
||||
|
||||
remove_obj(obj) {
|
||||
if (this[obj.toString()] === this.objects[obj.toString()])
|
||||
delete this[obj.toString()];
|
||||
|
||||
delete this.objects[obj.toString()];
|
||||
delete this[obj.toString()];
|
||||
Object.unhide(this, obj.toString());
|
||||
},
|
||||
|
||||
components: {},
|
||||
|
@ -419,7 +419,6 @@ var gameobject = {
|
|||
|
||||
d ??= {};
|
||||
|
||||
var objects = {};
|
||||
fresh.objects ??= {};
|
||||
var curobjs = {};
|
||||
for (var o in this.objects)
|
||||
|
@ -446,15 +445,9 @@ var gameobject = {
|
|||
|
||||
transform() {
|
||||
var t = {};
|
||||
t.pos = this.get_pos(this.master);
|
||||
if (t.pos.every(x => x === 0)) delete t.pos;
|
||||
t.pos = this.get_pos(this.master).map(x => Math.places(x, 0));
|
||||
t.angle = Math.places(this.get_angle(this.master), 4);
|
||||
if (t.angle === 0) delete t.angle;
|
||||
return t;
|
||||
t.scale = this.get_scale(this.master);
|
||||
t.scale = t.scale.map((x, i) => x / this.ur.fresh.scale[i]);
|
||||
t.scale = t.scale.map(x => Math.places(x, 3));
|
||||
if (t.scale.every(x => x === 1)) delete t.scale;
|
||||
t.scale = this.get_scale(this.master).map(x => Math.places(x, 2));;
|
||||
return t;
|
||||
},
|
||||
|
||||
|
@ -466,9 +459,16 @@ var gameobject = {
|
|||
return phys;
|
||||
},
|
||||
|
||||
phys_mat() {
|
||||
return {
|
||||
friction: this.friction,
|
||||
elasticity: this.elasticity
|
||||
}
|
||||
},
|
||||
|
||||
dup(diff) {
|
||||
var n = this.master.spawn(this.ur);
|
||||
Object.totalmerge(n, this.instance_obj());
|
||||
Object.totalmerge(n, this.transform());
|
||||
return n;
|
||||
},
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ Mum.text = Mum.extend({
|
|||
this.height = this.wh.y;
|
||||
var aa = [0,1].sub(params.anchor);
|
||||
var pos = cursor.add(params.wh.scale(aa)).add(params.offset);
|
||||
gui.font_set(params.font);
|
||||
// gui.font_set(params.font);
|
||||
render.text(params.str, pos, params.font_size, params.color, this.width, undefined, params.caret);
|
||||
},
|
||||
|
||||
|
|
|
@ -129,6 +129,15 @@ render.image = function(tex, pos, rotation = 0, color = Color.white, dimensions
|
|||
return bbox.fromcwh([0,0], [tex.width,tex.height]);
|
||||
}
|
||||
|
||||
render.fontcache = {};
|
||||
render.set_font = function(path, size) {
|
||||
var fontstr = `${path}-${size}`;
|
||||
if (!render.fontcache[fontstr]) render.fontcache[fontstr] = os.make_font(path, size);
|
||||
|
||||
gui.font_set(render.fontcache[fontstr]);
|
||||
render.font = render.fontcache[fontstr];
|
||||
}
|
||||
|
||||
render.doc = "Draw shapes in screen space.";
|
||||
render.circle.doc = "Draw a circle at pos, with a given radius and color.";
|
||||
render.cross.doc = "Draw a cross centered at pos, with arm length size.";
|
||||
|
|
|
@ -199,6 +199,8 @@ Cmdline.register_order("edit", function() {
|
|||
global.mixin("scripts/editor.js");
|
||||
use("editorconfig.js");
|
||||
use("config.js");
|
||||
render.set_font("fonts/c64.ttf", 8);
|
||||
console.info(`set font with linegap ${render.font.linegap}`);
|
||||
editor.enter_editor();
|
||||
});
|
||||
}, "Edit the project in this folder. Give it the name of an UR to edit that specific object.", "?UR?");
|
||||
|
|
|
@ -560,7 +560,7 @@ JSValue arb2js(cpArbiter *arb)
|
|||
JS_SetPropertyStr(js, obj, "normal", vec22js((HMM_Vec2)cpArbiterGetNormal(arb)));
|
||||
JS_SetPropertyStr(js, obj, "obj", JS_DupValue(js,go2->ref));
|
||||
JS_SetPropertyStr(js, obj, "shape", JS_DupValue(js, pshape->ref));
|
||||
JS_SetPropertyStr(js, obj, "point", vec22js((HMM_Vec2)cpArbiterGetPointA(arb, 0)));
|
||||
// JS_SetPropertyStr(js, obj, "point", vec22js((HMM_Vec2)cpArbiterGetPointA(arb, 0)));
|
||||
|
||||
HMM_Vec2 srfv;
|
||||
srfv.cp = cpArbiterGetSurfaceVelocity(arb);
|
||||
|
|
|
@ -167,7 +167,9 @@ sg_buffer texcoord_floats(float *f, int verts, int comp)
|
|||
|
||||
return sg_make_buffer(&(sg_buffer_desc){
|
||||
.data.ptr = packed,
|
||||
.data.size = sizeof(unsigned short) * verts});
|
||||
.data.size = sizeof(unsigned short) * verts,
|
||||
.label = "tex coord vert buffer",
|
||||
});
|
||||
}
|
||||
|
||||
sg_buffer normal_floats(float *f, int verts, int comp)
|
||||
|
@ -178,7 +180,9 @@ sg_buffer normal_floats(float *f, int verts, int comp)
|
|||
|
||||
return sg_make_buffer(&(sg_buffer_desc){
|
||||
.data.ptr = packed_norms,
|
||||
.data.size = sizeof(uint32_t) * verts});
|
||||
.data.size = sizeof(uint32_t) * verts,
|
||||
.label = "normal vert buffer",
|
||||
});
|
||||
}
|
||||
|
||||
HMM_Vec3 index_to_vert(uint32_t idx, float *f)
|
||||
|
@ -195,9 +199,11 @@ void mesh_add_primitive(mesh *mesh, cgltf_primitive *prim)
|
|||
memcpy(idxs, cgltf_buffer_view_data(prim->indices->buffer_view), sizeof(uint16_t) * c);
|
||||
|
||||
mesh->bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
|
||||
.data.ptr = idxs,
|
||||
.data.size = sizeof(uint16_t) * c,
|
||||
.type = SG_BUFFERTYPE_INDEXBUFFER});
|
||||
.data.ptr = idxs,
|
||||
.data.size = sizeof(uint16_t) * c,
|
||||
.type = SG_BUFFERTYPE_INDEXBUFFER,
|
||||
.label = "mesh index buffer",
|
||||
});
|
||||
|
||||
mesh->idx_count = c;
|
||||
} else {
|
||||
|
@ -232,8 +238,10 @@ void mesh_add_primitive(mesh *mesh, cgltf_primitive *prim)
|
|||
switch (attribute.type) {
|
||||
case cgltf_attribute_type_position:
|
||||
mesh->bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.data.ptr = vs,
|
||||
.data.size = sizeof(float) * n});
|
||||
.data.ptr = vs,
|
||||
.data.size = sizeof(float) * n,
|
||||
.label = "mesh vert buffer"
|
||||
});
|
||||
break;
|
||||
|
||||
case cgltf_attribute_type_normal:
|
||||
|
|
|
@ -209,7 +209,8 @@ void debugdraw_init()
|
|||
|
||||
point_bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(struct point_vertex)*v_amt,
|
||||
.usage = SG_USAGE_STREAM
|
||||
.usage = SG_USAGE_STREAM,
|
||||
.label = "point vertex buffer"
|
||||
});
|
||||
|
||||
line_shader = sg_make_shader(line_shader_desc(sg_query_backend()));
|
||||
|
@ -233,13 +234,15 @@ void debugdraw_init()
|
|||
|
||||
line_bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(struct line_vert)*v_amt,
|
||||
.usage = SG_USAGE_STREAM
|
||||
.usage = SG_USAGE_STREAM,
|
||||
.label = "line vertex buffer",
|
||||
});
|
||||
|
||||
line_bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(uint16_t)*v_amt,
|
||||
.usage = SG_USAGE_STREAM,
|
||||
.type = SG_BUFFERTYPE_INDEXBUFFER
|
||||
.type = SG_BUFFERTYPE_INDEXBUFFER,
|
||||
.label = "line index buffer",
|
||||
});
|
||||
|
||||
csg = sg_make_shader(circle_shader_desc(sg_query_backend()));
|
||||
|
@ -266,6 +269,7 @@ void debugdraw_init()
|
|||
circle_bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(struct circle_vertex)*v_amt,
|
||||
.usage = SG_USAGE_STREAM,
|
||||
.label = "circle vert buffer",
|
||||
});
|
||||
|
||||
float circleverts[8] = {
|
||||
|
@ -278,6 +282,7 @@ void debugdraw_init()
|
|||
circle_bind.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.data = (sg_range){.ptr = circleverts, .size = sizeof(float)*8},
|
||||
.usage = SG_USAGE_IMMUTABLE,
|
||||
.label = "circle quarter buffer",
|
||||
});
|
||||
|
||||
grid_shader = sg_make_shader(grid_shader_desc(sg_query_backend()));
|
||||
|
@ -315,12 +320,14 @@ void debugdraw_init()
|
|||
.size = sizeof(struct poly_vertex)*v_amt,
|
||||
.usage = SG_USAGE_STREAM,
|
||||
.type = SG_BUFFERTYPE_VERTEXBUFFER,
|
||||
.label = "poly vert buffer",
|
||||
});
|
||||
|
||||
poly_bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(uint32_t)*6*v_amt,
|
||||
.usage = SG_USAGE_STREAM,
|
||||
.type = SG_BUFFERTYPE_INDEXBUFFER
|
||||
.type = SG_BUFFERTYPE_INDEXBUFFER,
|
||||
.label = "poly index buffer"
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -17,18 +17,12 @@
|
|||
#include "stb_image_write.h"
|
||||
#include "stb_rect_pack.h"
|
||||
#include "stb_truetype.h"
|
||||
#include "stb_ds.h"
|
||||
|
||||
#include "HandmadeMath.h"
|
||||
|
||||
struct sFont *font;
|
||||
struct sFont *use_font;
|
||||
|
||||
static struct {
|
||||
char *key;
|
||||
struct sFont *value;
|
||||
} *fonthash = NULL;
|
||||
|
||||
#define max_chars 10000
|
||||
#define max_chars 100000
|
||||
|
||||
static sg_shader fontshader;
|
||||
static sg_bindings bind_text;
|
||||
|
@ -74,7 +68,8 @@ void font_init() {
|
|||
|
||||
bind_text.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.data = SG_RANGE(text_verts),
|
||||
.usage = SG_USAGE_IMMUTABLE
|
||||
.usage = SG_USAGE_IMMUTABLE,
|
||||
.label = "text rectangle buffer",
|
||||
});
|
||||
|
||||
bind_text.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||
|
@ -84,31 +79,19 @@ void font_init() {
|
|||
.label = "text buffer"
|
||||
});
|
||||
|
||||
font_set("fonts/c64.ttf");
|
||||
bind_text.fs.images[0] = font->texID;
|
||||
bind_text.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){});
|
||||
}
|
||||
|
||||
void font_set(const char *path)
|
||||
void font_free(font *f)
|
||||
{
|
||||
if (shlen(fonthash) == 0) sh_new_arena(fonthash);
|
||||
int index = shgeti(fonthash, path);
|
||||
if (index != -1) {
|
||||
if (font == fonthash[index].value) return;
|
||||
font = fonthash[index].value;
|
||||
bind_text.fs.images[0] = font->texID;
|
||||
return;
|
||||
}
|
||||
sg_destroy_image(f->texID);
|
||||
free(f);
|
||||
}
|
||||
|
||||
struct sFont *newfont = MakeFont(path, 8);
|
||||
if (!newfont) {
|
||||
YughError("Could not make font from %s.", path);
|
||||
return;
|
||||
}
|
||||
|
||||
font = newfont;
|
||||
shput(fonthash, path, newfont);
|
||||
bind_text.fs.images[0] = font->texID;
|
||||
void font_set(font *f)
|
||||
{
|
||||
use_font = f;
|
||||
bind_text.fs.images[0] = f->texID;
|
||||
}
|
||||
|
||||
struct sFont *MakeSDFFont(const char *fontfile, int height)
|
||||
|
@ -145,6 +128,10 @@ struct sFont *MakeFont(const char *fontfile, int height) {
|
|||
newfont->height = height;
|
||||
|
||||
unsigned char *ttf_buffer = slurp_file(fontfile, NULL);
|
||||
if (!ttf_buffer) {
|
||||
YughWarn("Could not find font at %s.");
|
||||
return NULL;
|
||||
}
|
||||
unsigned char *bitmap = malloc(packsize * packsize);
|
||||
|
||||
stbtt_packedchar glyphs[95];
|
||||
|
@ -163,19 +150,21 @@ struct sFont *MakeFont(const char *fontfile, int height) {
|
|||
}
|
||||
|
||||
stbtt_GetFontVMetrics(&fontinfo, &newfont->ascent, &newfont->descent, &newfont->linegap);
|
||||
newfont->emscale = stbtt_ScaleForMappingEmToPixels(&fontinfo, 16);
|
||||
newfont->linegap = (newfont->ascent - newfont->descent) * newfont->emscale;
|
||||
//newfont->emscale = stbtt_ScaleForMappingEmToPixels(&fontinfo, 16);
|
||||
newfont->emscale = stbtt_ScaleForPixelHeight(&fontinfo, height);
|
||||
newfont->linegap = (newfont->ascent - newfont->descent) * newfont->emscale*1.5;
|
||||
|
||||
newfont->texID = sg_make_image(&(sg_image_desc){
|
||||
.type = SG_IMAGETYPE_2D,
|
||||
.width = packsize,
|
||||
.height = packsize,
|
||||
.pixel_format = SG_PIXELFORMAT_R8,
|
||||
.usage = SG_USAGE_IMMUTABLE,
|
||||
.data.subimage[0][0] = {
|
||||
.ptr = bitmap,
|
||||
.size = packsize * packsize}});
|
||||
|
||||
.type = SG_IMAGETYPE_2D,
|
||||
.width = packsize,
|
||||
.height = packsize,
|
||||
.pixel_format = SG_PIXELFORMAT_R8,
|
||||
.usage = SG_USAGE_IMMUTABLE,
|
||||
.data.subimage[0][0] = {
|
||||
.ptr = bitmap,
|
||||
.size = packsize * packsize
|
||||
}
|
||||
});
|
||||
|
||||
for (unsigned char c = 32; c < 127; c++) {
|
||||
stbtt_packedchar glyph = glyphs[c - 32];
|
||||
|
@ -208,7 +197,7 @@ static int curchar = 0;
|
|||
void draw_underline_cursor(HMM_Vec2 pos, float scale, struct rgba color)
|
||||
{
|
||||
pos.Y -= 2;
|
||||
sdrawCharacter(font->Characters['_'], pos, scale, color);
|
||||
sdrawCharacter(use_font->Characters['_'], pos, scale, color);
|
||||
}
|
||||
|
||||
void draw_char_box(struct Character c, HMM_Vec2 cursor, float scale, struct rgba color)
|
||||
|
@ -270,10 +259,6 @@ void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgb
|
|||
curchar++;
|
||||
}
|
||||
|
||||
void text_settype(struct sFont *mfont) {
|
||||
font = mfont;
|
||||
}
|
||||
|
||||
const char *esc_color(const char *c, struct rgba *color, struct rgba defc)
|
||||
{
|
||||
struct rgba d;
|
||||
|
@ -303,6 +288,7 @@ const char *esc_color(const char *c, struct rgba *color, struct rgba defc)
|
|||
|
||||
struct boundingbox text_bb(const char *text, float scale, float lw, float tracking)
|
||||
{
|
||||
if (!use_font) return;
|
||||
struct rgba dummy;
|
||||
HMM_Vec2 cursor = {0,0};
|
||||
const char *line, *wordstart;
|
||||
|
@ -310,10 +296,10 @@ struct boundingbox text_bb(const char *text, float scale, float lw, float tracki
|
|||
|
||||
while (*line != '\0') {
|
||||
if (isblank(*line)) {
|
||||
cursor.X += font->Characters[*line].Advance * tracking * scale;
|
||||
cursor.X += use_font->Characters[*line].Advance * tracking * scale;
|
||||
line++;
|
||||
} else if (isspace(*line)) {
|
||||
cursor.Y -= scale * font->linegap;
|
||||
cursor.Y -= scale * use_font->linegap;
|
||||
cursor.X = 0;
|
||||
line++;
|
||||
} else {
|
||||
|
@ -324,26 +310,26 @@ struct boundingbox text_bb(const char *text, float scale, float lw, float tracki
|
|||
int wordWidth = 0;
|
||||
|
||||
while (!isspace(*line) && *line != '\0') {
|
||||
wordWidth += font->Characters[*line].Advance * tracking * scale;
|
||||
wordWidth += use_font->Characters[*line].Advance * tracking * scale;
|
||||
line++;
|
||||
}
|
||||
|
||||
if (lw > 0 && (cursor.X + wordWidth) >= lw) {
|
||||
cursor.X = 0;
|
||||
cursor.Y -= scale * font->linegap;
|
||||
cursor.Y -= scale * use_font->linegap;
|
||||
}
|
||||
|
||||
while (wordstart < line) {
|
||||
if (*wordstart == '\e')
|
||||
line = esc_color(wordstart, NULL, dummy);
|
||||
|
||||
cursor.X += font->Characters[*wordstart].Advance * tracking * scale;
|
||||
cursor.X += use_font->Characters[*wordstart].Advance * tracking * scale;
|
||||
wordstart++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cwh2bb((HMM_Vec2){0,0}, (HMM_Vec2){cursor.X,font->linegap-cursor.Y});
|
||||
return cwh2bb((HMM_Vec2){0,0}, (HMM_Vec2){cursor.X,use_font->linegap-cursor.Y});
|
||||
}
|
||||
|
||||
void check_caret(int caret, int l, HMM_Vec2 pos, float scale, struct rgba color)
|
||||
|
@ -354,6 +340,11 @@ void check_caret(int caret, int l, HMM_Vec2 pos, float scale, struct rgba color)
|
|||
|
||||
/* pos given in screen coordinates */
|
||||
int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, float lw, int caret, float tracking) {
|
||||
if (!use_font) {
|
||||
YughError("Cannot render text before a font is set.");
|
||||
return;
|
||||
}
|
||||
|
||||
int len = strlen(text);
|
||||
|
||||
HMM_Vec2 cursor = pos;
|
||||
|
@ -366,13 +357,13 @@ int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, f
|
|||
|
||||
while (*line != '\0') {
|
||||
if (isblank(*line)) {
|
||||
sdrawCharacter(font->Characters[*line], cursor, scale, usecolor);
|
||||
cursor.X += font->Characters[*line].Advance * tracking * scale;
|
||||
sdrawCharacter(use_font->Characters[*line], cursor, scale, usecolor);
|
||||
cursor.X += use_font->Characters[*line].Advance * tracking * scale;
|
||||
line++;
|
||||
check_caret(caret, line-drawstart, cursor, scale, usecolor);
|
||||
} else if (isspace(*line)) {
|
||||
sdrawCharacter(font->Characters[*line], cursor, scale, usecolor);
|
||||
cursor.Y -= scale * font->linegap;
|
||||
sdrawCharacter(use_font->Characters[*line], cursor, scale, usecolor);
|
||||
cursor.Y -= scale * use_font->linegap;
|
||||
cursor.X = pos.X;
|
||||
line++;
|
||||
check_caret(caret, line-drawstart, cursor, scale, usecolor);
|
||||
|
@ -385,23 +376,23 @@ int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, f
|
|||
|
||||
while (!isspace(*line) && *line != '\0') {
|
||||
|
||||
wordWidth += font->Characters[*line].Advance * tracking * scale;
|
||||
wordWidth += use_font->Characters[*line].Advance * tracking * scale;
|
||||
line++;
|
||||
}
|
||||
|
||||
if (lw > 0 && (cursor.X + wordWidth - pos.X) >= lw) {
|
||||
cursor.X = pos.X;
|
||||
cursor.Y -= scale * font->linegap;
|
||||
cursor.Y -= scale * use_font->linegap;
|
||||
}
|
||||
|
||||
while (wordstart < line) {
|
||||
if (*wordstart == '\e')
|
||||
wordstart = esc_color(wordstart, &usecolor, color);
|
||||
|
||||
sdrawCharacter(font->Characters[*wordstart], HMM_AddV2(cursor, HMM_MulV2F((HMM_Vec2){1,-1},scale)), scale, (rgba){0,0,0,255});
|
||||
sdrawCharacter(font->Characters[*wordstart], cursor, scale, usecolor);
|
||||
sdrawCharacter(use_font->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);
|
||||
|
||||
cursor.X += font->Characters[*wordstart].Advance * tracking * scale;
|
||||
cursor.X += use_font->Characters[*wordstart].Advance * tracking * scale;
|
||||
wordstart++;
|
||||
check_caret(caret, wordstart-drawstart, cursor, scale, usecolor);
|
||||
}
|
||||
|
|
|
@ -28,9 +28,13 @@ struct sFont {
|
|||
sg_image texID;
|
||||
};
|
||||
|
||||
typedef struct sFont font;
|
||||
|
||||
void font_free(font *f);
|
||||
|
||||
void font_init();
|
||||
struct sFont *MakeFont(const char *fontfile, int height);
|
||||
void font_set(const char *path);
|
||||
void font_set(font *f);
|
||||
void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgba color);
|
||||
void text_settype(struct sFont *font);
|
||||
struct boundingbox text_bb(const char *text, float scale, float lw, float tracking);
|
||||
|
|
|
@ -65,6 +65,7 @@ QJSCLASS(gameobject)
|
|||
QJSCLASS(emitter)
|
||||
QJSCLASS(dsp_node)
|
||||
QJSCLASS(texture)
|
||||
QJSCLASS(font)
|
||||
QJSCLASS(sprite)
|
||||
QJSCLASS(warp_gravity)
|
||||
QJSCLASS(warp_damp)
|
||||
|
@ -674,7 +675,7 @@ JSC_CCALL(gui_img,
|
|||
gui_draw_img(js2texture(argv[0]), t, js2boolean(argv[4]), js2vec2(argv[5]), 1.0, js2color(argv[6]));
|
||||
)
|
||||
|
||||
JSC_SCALL(gui_font_set, font_set(str))
|
||||
JSC_CCALL(gui_font_set, font_set(js2font(argv[0])))
|
||||
|
||||
static const JSCFunctionListEntry js_gui_funcs[] = {
|
||||
MIST_FUNC_DEF(gui, flush, 0),
|
||||
|
@ -1134,7 +1135,7 @@ JSValue js_gameobject_set_rscale(JSContext *js, JSValue this, JSValue val) { js2
|
|||
JSC_GETSET_BODY(velocity, Velocity, cvec2)
|
||||
JSValue js_gameobject_set_angularvelocity (JSContext *js, JSValue this, JSValue val) { cpBodySetAngularVelocity(js2gameobject(this)->body, HMM_TurnToRad*js2number(val)); }
|
||||
JSValue js_gameobject_get_angularvelocity (JSContext *js, JSValue this) { return number2js(HMM_RadToTurn*cpBodyGetAngularVelocity(js2gameobject(this)->body)); }
|
||||
JSC_GETSET_BODY(moi, Moment, number)
|
||||
//JSC_GETSET_BODY(moi, Moment, number)
|
||||
JSC_GETSET_BODY(torque, Torque, number)
|
||||
JSC_CCALL(gameobject_impulse, cpBodyApplyImpulseAtWorldPoint(js2gameobject(this)->body, js2vec2(argv[0]).cp, cpBodyGetPosition(js2gameobject(this)->body)))
|
||||
JSC_CCALL(gameobject_force, cpBodyApplyForceAtWorldPoint(js2gameobject(this)->body, js2vec2(argv[0]).cp, cpBodyGetPosition(js2gameobject(this)->body)))
|
||||
|
@ -1167,12 +1168,12 @@ static const JSCFunctionListEntry js_gameobject_funcs[] = {
|
|||
CGETSET_ADD(gameobject,layer),
|
||||
CGETSET_ADD(gameobject,warp_filter),
|
||||
CGETSET_ADD(gameobject,drawlayer),
|
||||
CGETSET_ADD(gameobject, rpos),
|
||||
CGETSET_ADD(gameobject, rangle),
|
||||
CGETSET_ADD(gameobject, rscale),
|
||||
CGETSET_ADD_HID(gameobject, rpos),
|
||||
CGETSET_ADD_HID(gameobject, rangle),
|
||||
CGETSET_ADD_HID(gameobject, rscale),
|
||||
CGETSET_ADD(gameobject, velocity),
|
||||
CGETSET_ADD(gameobject, angularvelocity),
|
||||
CGETSET_ADD(gameobject, moi),
|
||||
// CGETSET_ADD(gameobject, moi),
|
||||
CGETSET_ADD(gameobject, phys),
|
||||
CGETSET_ADD(gameobject, torque),
|
||||
MIST_FUNC_DEF(gameobject, impulse, 1),
|
||||
|
@ -1303,6 +1304,14 @@ static const JSCFunctionListEntry js_texture_funcs[] = {
|
|||
MIST_GET(texture, delays),
|
||||
};
|
||||
|
||||
JSC_GETSET(font, linegap, number)
|
||||
JSC_GET(font, height, number)
|
||||
|
||||
static const JSCFunctionListEntry js_font_funcs[] = {
|
||||
CGETSET_ADD(font, linegap),
|
||||
MIST_GET(font, height),
|
||||
};
|
||||
|
||||
JSValue js_constraint_set_max_force (JSContext *js, JSValue this, JSValue val) {
|
||||
cpConstraintSetMaxForce(js2constraint(this)->c, js2number(val));
|
||||
return JS_UNDEFINED;
|
||||
|
@ -1487,6 +1496,8 @@ JSC_CCALL(os_make_model,
|
|||
return ret;
|
||||
)
|
||||
|
||||
JSC_CCALL(os_make_font, return font2js(MakeFont(js2str(argv[0]), js2number(argv[1]))))
|
||||
|
||||
JSC_SCALL(os_system, system(str); )
|
||||
|
||||
static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
|
@ -1507,6 +1518,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
|||
MIST_FUNC_DEF(os, make_edge2d, 2),
|
||||
MIST_FUNC_DEF(os, make_model, 2),
|
||||
MIST_FUNC_DEF(os, make_texture, 1),
|
||||
MIST_FUNC_DEF(os, make_font, 2),
|
||||
};
|
||||
|
||||
#include "steam.h"
|
||||
|
@ -1525,6 +1537,7 @@ void ffi_load() {
|
|||
QJSCLASSPREP_FUNCS(warp_damp);
|
||||
QJSCLASSPREP_FUNCS(sprite);
|
||||
QJSCLASSPREP_FUNCS(texture);
|
||||
QJSCLASSPREP_FUNCS(font);
|
||||
QJSCLASSPREP_FUNCS(constraint);
|
||||
QJSCLASSPREP_FUNCS(window);
|
||||
QJSCLASSPREP_FUNCS(drawmodel);
|
||||
|
|
|
@ -25,11 +25,13 @@
|
|||
JS_FreeCString(js,str); \
|
||||
) \
|
||||
|
||||
#define MIST_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE, JS_DEF_CGETSET, 0, .u = { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } }
|
||||
|
||||
#define MIST_CGETSET_BASE(name, fgetter, fsetter, props) { name, props, JS_DEF_CGETSET, 0, .u = { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } }
|
||||
#define MIST_CGETSET_DEF(name, fgetter, fsetter) MIST_CGETSET_BASE(name, fgetter, fsetter, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE)
|
||||
#define MIST_CGETET_HID(name, fgetter, fsetter) MIST_CGETSET_BASE(name, fgetter, fsetter, JS_PROP_CONFIGURABLE)
|
||||
#define MIST_GET(name, fgetter) { #fgetter , JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE, JS_DEF_CGETSET, 0, .u = { .getset = { .get = { .getter = js_##name##_get_##fgetter } } } }
|
||||
|
||||
#define CGETSET_ADD(ID, ENTRY) MIST_CGETSET_DEF(#ENTRY, js_##ID##_get_##ENTRY, js_##ID##_set_##ENTRY)
|
||||
#define CGETSET_ADD_HID(ID, ENTRY) MIST_CGETSET_BASE(#ENTRY, js_##ID##_get_##ENTRY, js_##ID##_set_##ENTRY, JS_PROP_CONFIGURABLE)
|
||||
|
||||
#define JSC_CCALL(NAME, FN) JSValue js_##NAME (JSContext *js, JSValue this, int argc, JSValue *argv) { \
|
||||
JSValue ret = JS_UNDEFINED; \
|
||||
|
|
|
@ -80,7 +80,8 @@ void particle_init()
|
|||
|
||||
par_bind.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.data = (sg_range){.ptr = circleverts, .size = sizeof(float)*8},
|
||||
.usage = SG_USAGE_IMMUTABLE
|
||||
.usage = SG_USAGE_IMMUTABLE,
|
||||
.label = "particle quater buffer"
|
||||
});
|
||||
|
||||
par_bind.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){});
|
||||
|
|
|
@ -133,70 +133,89 @@ static struct {
|
|||
sg_shader shader;
|
||||
} sg_shadow;
|
||||
|
||||
void trace_init_image(sg_image id, const sg_image_desc *d, void *data)
|
||||
{
|
||||
YughSpam("Init image %s", d->label);
|
||||
}
|
||||
|
||||
void trace_make_shader(const sg_shader_desc *d, sg_shader id, void *data)
|
||||
{
|
||||
YughSpam("Making shader %s", d->label);
|
||||
if (sg_query_shader_state(id) == SG_RESOURCESTATE_FAILED)
|
||||
YughError("FAILED MAKING A SHADER: %s\n%s\n%s", d->label);
|
||||
}
|
||||
|
||||
void trace_fail_shader(sg_shader id, void *data)
|
||||
{
|
||||
YughError("Shader %u did not compile.", id);
|
||||
}
|
||||
|
||||
void trace_destroy_shader(sg_shader id, void *data)
|
||||
{
|
||||
YughSpam("Destroyed shader %u.", id);
|
||||
}
|
||||
|
||||
void trace_fail_image(sg_image id, void *data)
|
||||
{
|
||||
sg_image_desc desc = sg_query_image_desc(id);
|
||||
YughError("Failed to make image %u %s", id, desc.label);
|
||||
}
|
||||
|
||||
void trace_make_pipeline(const sg_pipeline_desc *d, sg_pipeline id, void *data)
|
||||
{
|
||||
YughSpam("Making pipeline %u [%s].", id, d->label);
|
||||
}
|
||||
|
||||
void trace_apply_pipeline(sg_pipeline pip, void *data)
|
||||
{
|
||||
// YughSpam("Applying pipeline %u %s.", pip, sg_query_pipeline_desc(pip).label);
|
||||
}
|
||||
|
||||
void trace_fail_pipeline(sg_pipeline pip, void *data)
|
||||
{
|
||||
YughError("Failed pipeline %s", sg_query_pipeline_desc(pip).label);
|
||||
}
|
||||
|
||||
void trace_make_attachments(const sg_attachment_desc *d, sg_attachments result, void *data)
|
||||
{
|
||||
YughSpam("Making attachments %s", "IMPLEMENT");
|
||||
}
|
||||
|
||||
void trace_begin_pass(sg_pass pass, const sg_pass_action *action, void *data)
|
||||
{
|
||||
// YughSpam("Begin pass %s", pass.label);
|
||||
}
|
||||
|
||||
#define SG_TRACE_SET(NAME) \
|
||||
void trace_alloc_##NAME (sg_##NAME id, void *data) \
|
||||
{ \
|
||||
sg_##NAME##_desc desc = sg_query_##NAME##_desc(id); \
|
||||
YughSpam("Alloc " #NAME " %d [%s]", id, desc.label); \
|
||||
} \
|
||||
\
|
||||
void trace_dealloc_##NAME(sg_##NAME id, void *data) \
|
||||
{ \
|
||||
sg_##NAME##_desc desc = sg_query_##NAME##_desc(id); \
|
||||
YughSpam("Dealloc " #NAME " %d [%s]", id, desc.label); \
|
||||
} \
|
||||
\
|
||||
void trace_make_##NAME(sg_##NAME##_desc *desc, void *data) \
|
||||
{ \
|
||||
YughSpam("Make " #NAME " [%s]", desc->label); \
|
||||
} \
|
||||
\
|
||||
void trace_destroy_##NAME(sg_##NAME id, void *data) \
|
||||
{ \
|
||||
sg_##NAME##_desc desc = sg_query_##NAME##_desc(id); \
|
||||
YughSpam("Destroy " #NAME " %d [%s]", id, desc.label); \
|
||||
} \
|
||||
\
|
||||
void trace_init_##NAME(sg_##NAME id, sg_##NAME##_desc *desc, void *data) \
|
||||
{ \
|
||||
YughSpam("Init " #NAME " %d [%s]", id, desc->label); \
|
||||
} \
|
||||
\
|
||||
void trace_uninit_##NAME(sg_##NAME id, void *data) \
|
||||
{ \
|
||||
sg_##NAME##_desc desc = sg_query_##NAME##_desc(id); \
|
||||
YughSpam("Init " #NAME " %d [%s]", id, desc.label); \
|
||||
} \
|
||||
\
|
||||
void trace_fail_##NAME(sg_##NAME id, void *data) \
|
||||
{ \
|
||||
sg_##NAME##_desc desc = sg_query_##NAME##_desc(id); \
|
||||
YughError("Failed " #NAME " %d: %s", id, desc.label); \
|
||||
} \
|
||||
|
||||
SG_TRACE_SET(buffer)
|
||||
SG_TRACE_SET(image)
|
||||
SG_TRACE_SET(sampler)
|
||||
SG_TRACE_SET(shader)
|
||||
SG_TRACE_SET(pipeline)
|
||||
SG_TRACE_SET(attachments)
|
||||
|
||||
#define SG_HOOK_SET(NAME) \
|
||||
.alloc_##NAME = trace_alloc_##NAME, \
|
||||
.dealloc_##NAME = trace_dealloc_##NAME, \
|
||||
.init_##NAME = trace_init_##NAME, \
|
||||
.uninit_##NAME = trace_uninit_##NAME, \
|
||||
.fail_##NAME = trace_fail_##NAME, \
|
||||
.destroy_##NAME = trace_destroy_##NAME, \
|
||||
.make_##NAME = trace_make_##NAME \
|
||||
|
||||
void trace_append_buffer(sg_buffer id, sg_range *data, void *user)
|
||||
{
|
||||
sg_buffer_desc desc = sg_query_buffer_desc(id);
|
||||
YughSpam("Appending buffer %d [%s]", id, desc.label);
|
||||
}
|
||||
|
||||
static sg_trace_hooks hooks = {
|
||||
.fail_shader = trace_fail_shader,
|
||||
.make_shader = trace_make_shader,
|
||||
.destroy_shader = trace_destroy_shader,
|
||||
.fail_image = trace_fail_image,
|
||||
.init_image = trace_init_image,
|
||||
.make_pipeline = trace_make_pipeline,
|
||||
.fail_pipeline = trace_fail_pipeline,
|
||||
.apply_pipeline = trace_apply_pipeline,
|
||||
.begin_pass = trace_begin_pass,
|
||||
.make_attachments = trace_make_attachments,
|
||||
SG_HOOK_SET(buffer),
|
||||
SG_HOOK_SET(image),
|
||||
SG_HOOK_SET(shader),
|
||||
SG_HOOK_SET(sampler),
|
||||
SG_HOOK_SET(pipeline),
|
||||
SG_HOOK_SET(attachments),
|
||||
.append_buffer = trace_append_buffer
|
||||
};
|
||||
|
||||
void render_init() {
|
||||
|
@ -256,6 +275,7 @@ void render_init() {
|
|||
sg_gif.bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(gif_quad),
|
||||
.data = gif_quad,
|
||||
.label = "gif vert buffer",
|
||||
});
|
||||
sg_gif.bind.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){});
|
||||
|
||||
|
@ -274,7 +294,8 @@ void render_init() {
|
|||
sg_crt.bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(crt_quad),
|
||||
.type = SG_BUFFERTYPE_VERTEXBUFFER,
|
||||
.usage = SG_USAGE_IMMUTABLE
|
||||
.usage = SG_USAGE_IMMUTABLE,
|
||||
.label = "crt vert buffer",
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -148,6 +148,7 @@ void sprite_initialize() {
|
|||
.size = sizeof(struct slice9_vert) * 100,
|
||||
.type = SG_BUFFERTYPE_VERTEXBUFFER,
|
||||
.usage = SG_USAGE_STREAM,
|
||||
.label = "slice9 buffer"
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue