2023.11 release!

main
Dominik Madarász 2023-11-26 22:21:57 +01:00
parent ed13bab0b9
commit 2562509584
25 changed files with 293 additions and 164 deletions

View File

@ -1515,11 +1515,16 @@ ffi.cdef([[
//lcpp INF [0000] vec2: macro name but used as C declaration in:vec2* uvs; //lcpp INF [0000] vec2: macro name but used as C declaration in:vec2* uvs;
//lcpp INF [0000] vec4: macro name but used as C declaration in:vec4 bounds; //lcpp INF [0000] vec4: macro name but used as C declaration in:vec4 bounds;
//lcpp INF [0000] vec4: macro name but used as C declaration in:vec4 core; //lcpp INF [0000] vec4: macro name but used as C declaration in:vec4 core;
//lcpp INF [0000] vec2: macro name but used as C declaration in:vec2 pivot;
//lcpp INF [0000] vec4: macro name but used as C declaration in:vec4 gamepad; //lcpp INF [0000] vec4: macro name but used as C declaration in:vec4 gamepad;
//lcpp INF [0000] vec2: macro name but used as C declaration in:vec2 fire; //lcpp INF [0000] vec2: macro name but used as C declaration in:vec2 fire;
//lcpp INF [0000] vec4: macro name but used as C declaration in:vec4 pos; //lcpp INF [0000] vec4: macro name but used as C declaration in:vec4 pos;
//lcpp INF [0000] vec2: macro name but used as C declaration in:vec2 sca; //lcpp INF [0000] vec2: macro name but used as C declaration in:vec2 sca;
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*draw_rect_func)(void* userdata, const char *skin, vec4 rect); //lcpp INF [0000] vec4: macro name but used as C declaration in:void (*drawrect)(void* userdata, const char *skin, vec4 rect);
//lcpp INF [0000] vec2: macro name but used as C declaration in:void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
//lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 gui_getskinsize(const char *skin);
//lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 gui_getskinsize(const char *skin);
//lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 gui_getskinsize(const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in:API void gui_panel(int id, vec4 rect, const char *skin); //lcpp INF [0000] vec4: macro name but used as C declaration in:API void gui_panel(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC void gui_panel(int id, vec4 rect, const char *skin); //lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC void gui_panel(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in: void gui_panel(int id, vec4 rect, const char *skin); //lcpp INF [0000] vec4: macro name but used as C declaration in: void gui_panel(int id, vec4 rect, const char *skin);
@ -1621,12 +1626,12 @@ ffi.cdef([[
//lcpp INF [0000] vec3: macro name but used as C declaration in:API vec3 editor_pick(float mouse_x, float mouse_y); //lcpp INF [0000] vec3: macro name but used as C declaration in:API vec3 editor_pick(float mouse_x, float mouse_y);
//lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC vec3 editor_pick(float mouse_x, float mouse_y); //lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC vec3 editor_pick(float mouse_x, float mouse_y);
//lcpp INF [0000] vec3: macro name but used as C declaration in: vec3 editor_pick(float mouse_x, float mouse_y); //lcpp INF [0000] vec3: macro name but used as C declaration in: vec3 editor_pick(float mouse_x, float mouse_y);
//lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 editor_glyph(int x, int y, unsigned cp); //lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 editor_glyph(int x, int y, const char *style, unsigned codepoint);
//lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 editor_glyph(int x, int y, unsigned cp); //lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 editor_glyph(int x, int y, const char *style, unsigned codepoint);
//lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 editor_glyph(int x, int y, unsigned cp); //lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 editor_glyph(int x, int y, const char *style, unsigned codepoint);
//lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 editor_glyphstr(int x, int y, const char *utf8); //lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 editor_glyphs(int x, int y, const char *style, const char *utf8);
//lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 editor_glyphstr(int x, int y, const char *utf8); //lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 editor_glyphs(int x, int y, const char *style, const char *utf8);
//lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 editor_glyphstr(int x, int y, const char *utf8); //lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 editor_glyphs(int x, int y, const char *style, const char *utf8);
typedef struct FILE FILE; typedef struct FILE FILE;
typedef long int ptrdiff_t; typedef long int ptrdiff_t;
typedef long unsigned int size_t; typedef long unsigned int size_t;
@ -3257,6 +3262,7 @@ typedef struct atlas_slice_frame_t {
vec4 bounds; vec4 bounds;
bool has_9slice; bool has_9slice;
vec4 core; vec4 core;
vec2 pivot;
} atlas_slice_frame_t; } atlas_slice_frame_t;
typedef struct atlas_slice_t { typedef struct atlas_slice_t {
unsigned name; unsigned name;
@ -3288,7 +3294,7 @@ unsigned play;
bool paused; bool paused;
struct atlas_t *a; struct atlas_t *a;
} sprite_t; } sprite_t;
enum { OBJTYPE_sprite_t = 10 }; typedef struct { unsigned static_assert_on_L__LINE__ : !!(10 <= 255); } static_assert_on_Lconcat(_L,3937)___COUNTER__; typedef struct { unsigned static_assert_on_L__LINE__ : !!(sizeof(sprite_t)); } static_assert_on_Lconcat(_L,3937)___COUNTER__;; enum { OBJTYPE_sprite_t = 10 }; typedef struct { unsigned static_assert_on_L__LINE__ : !!(10 <= 255); } static_assert_on_Lconcat(_L,3938)___COUNTER__; typedef struct { unsigned static_assert_on_L__LINE__ : !!(sizeof(sprite_t)); } static_assert_on_Lconcat(_L,3938)___COUNTER__;;
void sprite_ctor(sprite_t *s); void sprite_ctor(sprite_t *s);
void sprite_dtor(sprite_t *s); void sprite_dtor(sprite_t *s);
void sprite_tick(sprite_t *s); void sprite_tick(sprite_t *s);
@ -3298,12 +3304,14 @@ enum { OBJTYPE_sprite_t = 10 }; typedef struct { unsigned static_assert_on
void sprite_del(sprite_t *s); void sprite_del(sprite_t *s);
void sprite_setanim(sprite_t *s, unsigned name); void sprite_setanim(sprite_t *s, unsigned name);
typedef struct guiskin_t { typedef struct guiskin_t {
void (*draw_rect_func)(void* userdata, const char *skin, vec4 rect); void (*drawrect)(void* userdata, const char *skin, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
void (*free)(void* userdata); void (*free)(void* userdata);
void *userdata; void *userdata;
} guiskin_t; } guiskin_t;
void gui_pushskin(guiskin_t skin); void gui_pushskin(guiskin_t skin);
void* gui_userdata(); void* gui_userdata();
vec2 gui_getskinsize(const char *skin);
void gui_panel(int id, vec4 rect, const char *skin); void gui_panel(int id, vec4 rect, const char *skin);
bool gui_button(int id, vec4 rect, const char *skin); bool gui_button(int id, vec4 rect, const char *skin);
void gui_popskin(); void gui_popskin();
@ -3679,8 +3687,8 @@ EDITOR_WINDOW_NK_SMALL,
vec3 editor_pick(float mouse_x, float mouse_y); vec3 editor_pick(float mouse_x, float mouse_y);
char* editor_path(const char *path); char* editor_path(const char *path);
void editor_setmouse(int x, int y); void editor_setmouse(int x, int y);
vec2 editor_glyph(int x, int y, unsigned cp); vec2 editor_glyph(int x, int y, const char *style, unsigned codepoint);
vec2 editor_glyphstr(int x, int y, const char *utf8); vec2 editor_glyphs(int x, int y, const char *style, const char *utf8);
void editor_gizmos(int dim); void editor_gizmos(int dim);
int editor_send(const char *cmd); int editor_send(const char *cmd);
const char* editor_recv(int jobid, double timeout_ss); const char* editor_recv(int jobid, double timeout_ss);

View File

@ -37,11 +37,16 @@ int main() {
printf("%s\n", "Button pressed!"); printf("%s\n", "Button pressed!");
} }
gui_panel(vec4(40,140, 320, 40), "vial"); gui_panel(vec4(40,140, 320, 20*skinned->scale), "vial");
gui_panel(vec4(40+9*skinned->scale,140+2*skinned->scale, 200, 64), "hp"); gui_panel(vec4(40,140, 200, 14*skinned->scale), "hp");
gui_panel(vec4(40,240, 240, 20*skinned->scale), "vial");
gui_panel(vec4(40,240, 160, 14*skinned->scale), "mp");
gui_panel(vec4(40,230, 280, 40), "vial"); vec2 badge_size = gui_getskinsize("badge");
gui_panel(vec4(40+9*skinned->scale,230+2*skinned->scale, 280-18*skinned->scale, 64), "mp"); badge_size.x += 2; // padding
gui_panel(vec4(60+badge_size.x*0,320, 1, 1), "badge");
gui_panel(vec4(60+badge_size.x*1,320, 1, 1), "badge");
gui_panel(vec4(60+badge_size.x*2,320, 1, 1), "badge_empty");
} }
gui_popskin(); gui_popskin();

Binary file not shown.

View File

@ -162,8 +162,8 @@ int editor_toolbar(int x, int y, int incw, int inch, const char *sym) {
for each_array(codepoints, uint32_t, g) { for each_array(codepoints, uint32_t, g) {
int selected = oo ? is_hovering(vec4(ix,iy,ix+inc,iy+inc),vec2(ox,oy)) : 0; int selected = oo ? is_hovering(vec4(ix,iy,ix+inc,iy+inc),vec2(ox,oy)) : 0;
int hovering = dragging ? 0 : is_hovering(vec4(ix,iy,ix+inc,iy+inc), vec2(mx,my)); int hovering = dragging ? 0 : is_hovering(vec4(ix,iy,ix+inc,iy+inc), vec2(mx,my));
const char *str8 = va("%s%s", selected || hovering ? FONT_COLOR1 : FONT_COLOR2, codepoint_to_utf8(g)); const char *str8 = codepoint_to_utf8(g);
editor_glyphstr(ix + inc/8, iy + inc/3 + 2, str8); editor_glyphs(ix + inc/8, iy + inc/3 + 2, selected || hovering ? FONT_COLOR1 FONT_H1 : FONT_COLOR2 FONT_H1, str8);
ix += incw; ix += incw;
iy += inch; iy += inch;
} }
@ -251,13 +251,13 @@ int lit_edit(lit *obj) {
ICON_MDI_WEATHER_SUNNY // directional ICON_MDI_WEATHER_SUNNY // directional
ICON_MDI_LIGHTBULB_FLUORESCENT_TUBE_OUTLINE ICON_MDI_LIGHTBULB_FLUORESCENT_TUBE_OUTLINE
; ;
// editor_glyphstr(obj->pos.x+16,obj->pos.y-32,all_icons); // editor_glyphs(obj->pos.x+16,obj->pos.y-32,all_icons);
if( editor_selected(obj) ) { if( editor_selected(obj) ) {
obj->pos.x += input(KEY_RIGHT) - input(KEY_LEFT); obj->pos.x += input(KEY_RIGHT) - input(KEY_LEFT);
obj->pos.y += input(KEY_DOWN) - input(KEY_UP); obj->pos.y += input(KEY_DOWN) - input(KEY_UP);
obj->type = (obj->type + !!input_down(KEY_SPACE)) % 4; obj->type = (obj->type + !!input_down(KEY_SPACE)) % 4;
} }
editor_glyphstr(obj->pos.x,obj->pos.y,lit_icon(obj)); editor_glyphs(obj->pos.x,obj->pos.y,0,lit_icon(obj));
@ -331,7 +331,7 @@ int kid_edit(kid *obj) {
obj->pos.x += input(KEY_RIGHT) - input(KEY_LEFT); obj->pos.x += input(KEY_RIGHT) - input(KEY_LEFT);
obj->pos.y += input(KEY_DOWN) - input(KEY_UP); obj->pos.y += input(KEY_DOWN) - input(KEY_UP);
editor_glyphstr(obj->pos.x+16,obj->pos.y-16,ICON_MD_VIDEOGAME_ASSET); editor_glyphs(obj->pos.x+16,obj->pos.y-16,0,ICON_MD_VIDEOGAME_ASSET);
} }
return 1; return 1;
} }
@ -474,9 +474,9 @@ int main(){
int choice1 = editor_toolbar(window_width()-32, ui_has_menubar() ? 34 : 0, 0, 32, int choice1 = editor_toolbar(window_width()-32, ui_has_menubar() ? 34 : 0, 0, 32,
ICON_MD_VISIBILITY ICON_MD_VISIBILITY
ICON_MDI_ORBIT// ICON_MD_360 ICON_MD_360 // ICON_MDI_ORBIT
ICON_MD_ZOOM_IN // ICON_MD_ZOOM_OUT_MAP ICON_MD_LOUPE // ZOOM_OUT_MAP // ICON_MD_ZOOM_IN
ICON_MD_GRID_ON ); // ICON_MDI_LOUPE ICON_MDI_GRID ); ICON_MD_GRID_ON ); // ICON_MDI_GRID );
int choice2 = editor_toolbar(window_width()-32*2, ui_has_menubar() ? 34 : 0, -32, 0, ICON_MD_SQUARE_FOOT ); int choice2 = editor_toolbar(window_width()-32*2, ui_has_menubar() ? 34 : 0, -32, 0, ICON_MD_SQUARE_FOOT );
if( choice1 > 0 ) { // clicked[>0] if( choice1 > 0 ) { // clicked[>0]

View File

@ -18056,6 +18056,7 @@ typedef struct atlas_slice_frame_t {
vec4 bounds; vec4 bounds;
bool has_9slice; bool has_9slice;
vec4 core; vec4 core;
vec2 pivot;
} atlas_slice_frame_t; } atlas_slice_frame_t;
typedef struct atlas_slice_t { typedef struct atlas_slice_t {
@ -18116,13 +18117,15 @@ API void sprite_setanim(sprite_t *s, unsigned name);
// game ui // game ui
typedef struct guiskin_t { typedef struct guiskin_t {
void (*draw_rect_func)(void* userdata, const char *skin, vec4 rect); void (*drawrect)(void* userdata, const char *skin, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
void (*free)(void* userdata); void (*free)(void* userdata);
void *userdata; void *userdata;
} guiskin_t; } guiskin_t;
API void gui_pushskin(guiskin_t skin); API void gui_pushskin(guiskin_t skin);
API void* gui_userdata(); API void* gui_userdata();
API vec2 gui_getskinsize(const char *skin);
// -- // --
API void gui_panel(int id, vec4 rect, const char *skin); API void gui_panel(int id, vec4 rect, const char *skin);
API bool gui_button(int id, vec4 rect, const char *skin); API bool gui_button(int id, vec4 rect, const char *skin);
@ -18724,8 +18727,8 @@ API vec3 editor_pick(float mouse_x, float mouse_y);
API char* editor_path(const char *path); API char* editor_path(const char *path);
API void editor_setmouse(int x, int y); API void editor_setmouse(int x, int y);
API vec2 editor_glyph(int x, int y, unsigned cp); API vec2 editor_glyph(int x, int y, const char *style, unsigned codepoint);
API vec2 editor_glyphstr(int x, int y, const char *utf8); API vec2 editor_glyphs(int x, int y, const char *style, const char *utf8);
API void editor_gizmos(int dim); API void editor_gizmos(int dim);
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
@ -357862,6 +357865,7 @@ static const unsigned table_middle_east[] = {
static const unsigned table_emoji[] = { static const unsigned table_emoji[] = {
// 0xE000, 0xEB4C, // Private use (emojis) // 0xE000, 0xEB4C, // Private use (emojis)
0xE000, 0xF8FF, // Private use (emojis+webfonts) 0xE000, 0xF8FF, // Private use (emojis+webfonts)
0xF0001,0xF1CC7,// Private use (icon mdi)
0 0
}; };
@ -358049,6 +358053,7 @@ typedef struct font_t {
unsigned num_glyphs; unsigned num_glyphs;
unsigned *cp2iter; unsigned *cp2iter;
unsigned *iter2cp; unsigned *iter2cp;
unsigned begin; // first glyph. used in cp2iter table to clamp into a lesser range
// font info and data // font info and data
int height; // bitmap height int height; // bitmap height
@ -358145,7 +358150,8 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
if( font_size <= 0 || font_size > 72 ) return; if( font_size <= 0 || font_size > 72 ) return;
if( !ttf_data || !ttf_len ) return; if( !ttf_data || !ttf_len ) return;
flags |= FONT_ASCII; // ensure this minimal range [0020-00FF] is always in if(!(flags & FONT_EM))
flags |= FONT_ASCII; // ensure this minimal range [0020-00FF] is almost always in
font_t *f = &fonts[index]; font_t *f = &fonts[index];
f->initialized = 1; f->initialized = 1;
@ -358205,12 +358211,13 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
// pack and create bitmap // pack and create bitmap
unsigned char *bitmap = (unsigned char*)MALLOC(f->height*f->width); unsigned char *bitmap = (unsigned char*)MALLOC(f->height*f->width);
int charCount = 0xFFFF; int charCount = *array_back(sorted) - sorted[0] + 1; // 0xEFFFF;
f->begin = sorted[0];
f->cdata = (stbtt_packedchar*)CALLOC(1, sizeof(stbtt_packedchar) * charCount); f->cdata = (stbtt_packedchar*)CALLOC(1, sizeof(stbtt_packedchar) * charCount);
f->iter2cp = (unsigned*)CALLOC( 1, sizeof(unsigned) * charCount ); f->iter2cp = (unsigned*)MALLOC( sizeof(unsigned) * charCount );
for( int i = 0; i < charCount; ++i ) f->iter2cp[i] = 0xFFFD; // default invalid glyph f->cp2iter = (unsigned*)MALLOC( sizeof(unsigned) * charCount );
f->cp2iter = (unsigned*)CALLOC( 1, sizeof(unsigned) * charCount ); for( int i = 0; i < charCount; ++i )
for( int i = 0; i < charCount; ++i ) f->cp2iter[i] = 0xFFFD; // default invalid glyph f->iter2cp[i] = f->cp2iter[i] = 0xFFFD; // default invalid glyph
stbtt_pack_context pc; stbtt_pack_context pc;
if( !stbtt_PackBegin(&pc, bitmap, f->width, f->height, 0, 1, NULL) ) { if( !stbtt_PackBegin(&pc, bitmap, f->width, f->height, 0, 1, NULL) ) {
@ -358224,11 +358231,11 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
while( i < (num-1) && (sorted[i+1]-sorted[i]) == 1 ) end = sorted[++i]; while( i < (num-1) && (sorted[i+1]-sorted[i]) == 1 ) end = sorted[++i];
//printf("(%d,%d)", (unsigned)begin, (unsigned)end); //printf("(%d,%d)", (unsigned)begin, (unsigned)end);
if( stbtt_PackFontRange(&pc, ttf_data, 0, f->font_size, begin, end - begin + 1, (stbtt_packedchar*)f->cdata + begin) ) { if( stbtt_PackFontRange(&pc, ttf_data, 0, f->font_size, begin, end - begin + 1, (stbtt_packedchar*)f->cdata + begin - f->begin) ) {
for( int j = begin; j <= end; ++j ) { for( uint64_t cp = begin; cp <= end; ++cp ) {
// unicode->index runtime lookup // unicode->index runtime lookup
f->cp2iter[ j ] = count; f->cp2iter[ cp - f->begin ] = count;
f->iter2cp[ count++ ] = j; f->iter2cp[ count++ ] = cp;
} }
} else { } else {
PRINTF("!Failed to pack atlas font. Likely out of texture mem."); PRINTF("!Failed to pack atlas font. Likely out of texture mem.");
@ -358260,7 +358267,7 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
for (int i = 0; i < f->num_glyphs; i++) { for (int i = 0; i < f->num_glyphs; i++) {
int cp = f->iter2cp[i]; int cp = f->iter2cp[i];
if( cp == 0xFFFD ) continue; if( cp == 0xFFFD ) continue;
stbtt_packedchar *cd = &f->cdata[ cp ]; stbtt_packedchar *cd = &f->cdata[ cp - f->begin ];
if (cd->y1 > max_y1) { if (cd->y1 > max_y1) {
max_y1 = cd->y1; max_y1 = cd->y1;
} }
@ -358327,8 +358334,8 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
unsigned cp = f->iter2cp[ i ]; unsigned cp = f->iter2cp[ i ];
if(cp == 0xFFFD) continue; if(cp == 0xFFFD) continue;
stbtt_packedchar *cd = &f->cdata[ cp ]; stbtt_packedchar *cd = &f->cdata[ cp - f->begin ];
// if(cd->x1==cd->x0) { f->iter2cp[i] = f->cp2iter[cp] = 0xFFFD; continue; } // if(cd->x1==cd->x0) { f->iter2cp[i] = f->cp2iter[cp - f->begin] = 0xFFFD; continue; }
int k1 = 0*f->num_glyphs + count; int k1 = 0*f->num_glyphs + count;
int k2 = 1*f->num_glyphs + count; ++count; int k2 = 1*f->num_glyphs + count; ++count;
@ -358532,7 +358539,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
} }
// convert to vbo data // convert to vbo data
int cp = ch; // f->cp2iter[ch]; int cp = ch - f->begin; // f->cp2iter[ch - f->begin];
//if(cp == 0xFFFD) continue; //if(cp == 0xFFFD) continue;
//if(cp > f->num_glyphs) cp = 0xFFFD; //if(cp > f->num_glyphs) cp = 0xFFFD;
@ -358948,6 +358955,12 @@ void *gui_userdata() {
return last_skin->userdata; return last_skin->userdata;
} }
vec2 gui_getskinsize(const char *skin) {
vec2 size={0};
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &size);
return size;
}
static static
gui_state_t *gui_getstate(int id) { gui_state_t *gui_getstate(int id) {
if (!ctl_states) map_init(ctl_states, less_int, hash_int); if (!ctl_states) map_init(ctl_states, less_int, hash_int);
@ -358972,13 +358985,13 @@ bool (gui_button)(int id, vec4 r, const char *skin) {
} }
char *btn = va("%s%s", skin?skin:"button", entry->held?"_press":entry->hover?"_hover":""); char *btn = va("%s%s", skin?skin:"button", entry->held?"_press":entry->hover?"_hover":"");
if (last_skin->draw_rect_func) last_skin->draw_rect_func(last_skin->userdata, btn, r); if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, r);
return was_clicked; return was_clicked;
} }
void (gui_panel)(int id, vec4 r, const char *skin) { void (gui_panel)(int id, vec4 r, const char *skin) {
if (last_skin->draw_rect_func) last_skin->draw_rect_func(last_skin->userdata, skin?skin:"panel", r); if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin?skin:"panel", r);
} }
/* skinned */ /* skinned */
@ -359006,15 +359019,25 @@ void skinned_draw_missing_rect(vec4 r) {
static static
void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r) { void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r) {
vec4 outer = f->bounds;
r.x -= f->pivot.x*scale;
r.y -= f->pivot.y*scale;
r.z += r.x;
r.w += r.y;
// Ensure dest rectangle is large enough to render the whole element
if ((r.z-r.x) < (outer.z-outer.x) * scale) {
r.z = r.x + (outer.z-outer.x) * scale;
}
if ((r.w-r.y) < (outer.w-outer.y) * scale) {
r.w = r.y + (outer.w-outer.y) * scale;
}
if (!f->has_9slice) { if (!f->has_9slice) {
gui_drawrect(a->tex, v42v2(f->bounds), 0xFFFFFFFF, v42v2(r)); gui_drawrect(a->tex, v42v2(f->bounds), 0xFFFFFFFF, v42v2(r));
return; return;
} }
r.z += r.x;
r.w += r.y;
vec4 outer = f->bounds;
vec4 core = f->core; vec4 core = f->core;
core.x += outer.x; core.x += outer.x;
core.y += outer.y; core.y += outer.y;
@ -359034,14 +359057,6 @@ void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r
vec4 bottom_middle_slice = {core.x, core.w, core.z, outer.w}; vec4 bottom_middle_slice = {core.x, core.w, core.z, outer.w};
vec4 bottom_right_slice = {core.z, core.w, outer.z, outer.w}; vec4 bottom_right_slice = {core.z, core.w, outer.z, outer.w};
// Ensure dest rectangle is large enough to render the whole element
if ((r.z-r.x) < (outer.z-outer.x) * scale) {
r.z = r.x + (outer.z-outer.x) * scale;
}
if ((r.w-r.y) < (outer.w-outer.y) * scale) {
r.w = r.y + (outer.w-outer.y) * scale;
}
vec4 top_left = {r.x, r.y, r.x + (core.x - outer.x) * scale, r.y + (core.y - outer.y) * scale}; vec4 top_left = {r.x, r.y, r.x + (core.x - outer.x) * scale, r.y + (core.y - outer.y) * scale};
vec4 top_right = {r.z - (outer.z - core.z) * scale, r.y, r.z, r.y + (core.y - outer.y) * scale}; vec4 top_right = {r.z - (outer.z - core.z) * scale, r.y, r.z, r.y + (core.y - outer.y) * scale};
vec4 bottom_left = {r.x, r.w - (outer.w - core.w) * scale, r.x + (core.x - outer.x) * scale, r.w}; vec4 bottom_left = {r.x, r.w - (outer.w - core.w) * scale, r.x + (core.x - outer.x) * scale, r.w};
@ -359074,13 +359089,24 @@ void skinned_draw_rect(void* userdata, const char *skin, vec4 r) {
else skinned_draw_sprite(a->scale, &a->atlas, f, r); else skinned_draw_sprite(a->scale, &a->atlas, f, r);
} }
void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (f) {
size->x = (f->bounds.z-f->bounds.x)*a->scale;
size->y = (f->bounds.w-f->bounds.y)*a->scale;
}
}
guiskin_t gui_skinned(const char *inifile, float scale) { guiskin_t gui_skinned(const char *inifile, float scale) {
skinned_t *a = REALLOC(0, sizeof(skinned_t)); skinned_t *a = REALLOC(0, sizeof(skinned_t));
a->atlas = atlas_create(inifile, 0); a->atlas = atlas_create(inifile, 0);
a->scale = scale?scale:1.0f; a->scale = scale?scale:1.0f;
guiskin_t skin={0}; guiskin_t skin={0};
skin.userdata = a; skin.userdata = a;
skin.draw_rect_func = skinned_draw_rect; skin.drawrect = skinned_draw_rect;
skin.getskinsize = skinned_getskinsize;
skin.free = skinned_free; skin.free = skinned_free;
return skin; return skin;
} }
@ -371040,6 +371066,14 @@ atlas_t atlas_create(const char *inifile, unsigned flags) {
a.slice_frames[index].core = vec4(x,y,x+z,y+w); a.slice_frames[index].core = vec4(x,y,x+z,y+w);
} }
else if ( strend(k, ".sl_pivot") ) {
array_reserve_(a.slice_frames, index);
float x,y;
sscanf(v, "%f,%f", &x, &y);
a.slice_frames[index].pivot = vec2(x,y);
}
else if( strend(k, ".frames") ) { else if( strend(k, ".frames") ) {
array_reserve_(a.anims, index); array_reserve_(a.anims, index);
@ -377149,27 +377183,31 @@ void editor_setmouse(int x, int y) {
glfwSetCursorPos( window_handle(), x, y ); glfwSetCursorPos( window_handle(), x, y );
} }
vec2 editor_glyph(int x, int y, unsigned cp) { vec2 editor_glyph(int x, int y, const char *style, unsigned codepoint) {
do_once {
// style: atlas size, unicode ranges and 6 font faces max // style: atlas size, unicode ranges and 6 font faces max
do_once font_face(FONT_FACE2, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048); font_face(FONT_FACE2, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048);
do_once font_face(FONT_FACE3, "materialdesignicons-webfont.ttf", 24.f, FONT_EM|FONT_2048); // {0xF68C /*ICON_MDI_MIN*/, 0xF1CC7/*ICON_MDI_MAX*/, 0}}, font_face(FONT_FACE3, "materialdesignicons-webfont.ttf", 24.f, FONT_EM|FONT_2048); // {0xF68C /*ICON_MDI_MIN*/, 0xF1CC7/*ICON_MDI_MAX*/, 0}},
// style: 10 colors max // style: 10 colors max
do_once font_color(FONT_COLOR1, WHITE); font_color(FONT_COLOR1, WHITE);
do_once font_color(FONT_COLOR2, RGBX(0xE8F1FF,128)); // GRAY); font_color(FONT_COLOR2, RGBX(0xE8F1FF,128)); // GRAY);
do_once font_color(FONT_COLOR3, YELLOW); font_color(FONT_COLOR3, YELLOW);
do_once font_color(FONT_COLOR4, ORANGE); font_color(FONT_COLOR4, ORANGE);
do_once font_color(FONT_COLOR5, CYAN); font_color(FONT_COLOR5, CYAN);
const char *sym = codepoint_to_utf8(cp);
font_goto(x,y);
return font_print(va("%s" FONT_H1 "%s", cp >= ICON_MDI_MIN ? FONT_FACE3 : FONT_FACE2, sym));
} }
vec2 editor_glyphstr(int x, int y, const char *utf8) { font_goto(x,y);
vec2 dim = {x,y}; vec2 pos = {x,y};
const char *sym = codepoint_to_utf8(codepoint);
return add2(pos, font_print(va("%s%s%s", style ? style : "", codepoint >= ICON_MDI_MIN ? FONT_FACE3 : FONT_FACE2, sym)));
}
vec2 editor_glyphs(int x, int y, const char *style, const char *utf8) {
vec2 pos = {x,y};
array(unsigned) codepoints = string32(utf8); array(unsigned) codepoints = string32(utf8);
for( int i = 0, end = array_count(codepoints); i < end; ++i) for( int i = 0, end = array_count(codepoints); i < end; ++i)
add2(dim, editor_glyph(dim.x,dim.y,codepoints[i])); pos = add2(pos, editor_glyph(pos.x,pos.y,style,codepoints[i]));
return dim; return pos;
} }
void editor_frame( void (*game)(unsigned, float, double) ) { void editor_frame( void (*game)(unsigned, float, double) ) {

View File

@ -1148,7 +1148,7 @@ ase_t* cute_aseprite_load_from_memory(const void* memory, int size, void* mem_ct
last_udata->has_text = 1; last_udata->has_text = 1;
last_udata->text = s_read_string(s); last_udata->text = s_read_string(s);
} }
if (flags & 2) { if (flags & 2) { //< @zpl-zak: removed else
last_udata->color.r = s_read_uint8(s); last_udata->color.r = s_read_uint8(s);
last_udata->color.g = s_read_uint8(s); last_udata->color.g = s_read_uint8(s);
last_udata->color.b = s_read_uint8(s); last_udata->color.b = s_read_uint8(s);
@ -1178,7 +1178,8 @@ ase_t* cute_aseprite_load_from_memory(const void* memory, int size, void* mem_ct
slice.center_y = (int)s_read_int32(s); slice.center_y = (int)s_read_int32(s);
slice.center_w = (int)s_read_uint32(s); slice.center_w = (int)s_read_uint32(s);
slice.center_h = (int)s_read_uint32(s); slice.center_h = (int)s_read_uint32(s);
} else if (flags & 2) { }
if (flags & 2) {
// Has pivot information. // Has pivot information.
slice.has_pivot = 1; slice.has_pivot = 1;
slice.pivot_x = (int)s_read_int32(s); slice.pivot_x = (int)s_read_int32(s);

View File

@ -700,7 +700,8 @@ atlas_t* atlas_loadfiles(array(char*) files, atlas_flags flags)
strcatf(&atlas_slices, "[%d].sl_9slice=%d\n", slice_idx, slice->has_center_as_9_slice); strcatf(&atlas_slices, "[%d].sl_9slice=%d\n", slice_idx, slice->has_center_as_9_slice);
if (slice->has_center_as_9_slice) if (slice->has_center_as_9_slice)
strcatf(&atlas_slices, "[%d].sl_core=%d,%d,%d,%d\n", slice_idx, slice->center_x, slice->center_y, slice->center_w, slice->center_h); strcatf(&atlas_slices, "[%d].sl_core=%d,%d,%d,%d\n", slice_idx, slice->center_x, slice->center_y, slice->center_w, slice->center_h);
if (slice->has_pivot)
strcatf(&atlas_slices, "[%d].sl_pivot=%d,%d\n", slice_idx, slice->pivot_x, slice->pivot_y);
slice_name = slice->name; slice_name = slice->name;
++slice_frame_idx; ++slice_frame_idx;
} }

View File

@ -511,27 +511,31 @@ void editor_setmouse(int x, int y) {
glfwSetCursorPos( window_handle(), x, y ); glfwSetCursorPos( window_handle(), x, y );
} }
vec2 editor_glyph(int x, int y, unsigned cp) { vec2 editor_glyph(int x, int y, const char *style, unsigned codepoint) {
do_once {
// style: atlas size, unicode ranges and 6 font faces max // style: atlas size, unicode ranges and 6 font faces max
do_once font_face(FONT_FACE2, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048); font_face(FONT_FACE2, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048);
do_once font_face(FONT_FACE3, "materialdesignicons-webfont.ttf", 24.f, FONT_EM|FONT_2048); // {0xF68C /*ICON_MDI_MIN*/, 0xF1CC7/*ICON_MDI_MAX*/, 0}}, font_face(FONT_FACE3, "materialdesignicons-webfont.ttf", 24.f, FONT_EM|FONT_2048); // {0xF68C /*ICON_MDI_MIN*/, 0xF1CC7/*ICON_MDI_MAX*/, 0}},
// style: 10 colors max // style: 10 colors max
do_once font_color(FONT_COLOR1, WHITE); font_color(FONT_COLOR1, WHITE);
do_once font_color(FONT_COLOR2, RGBX(0xE8F1FF,128)); // GRAY); font_color(FONT_COLOR2, RGBX(0xE8F1FF,128)); // GRAY);
do_once font_color(FONT_COLOR3, YELLOW); font_color(FONT_COLOR3, YELLOW);
do_once font_color(FONT_COLOR4, ORANGE); font_color(FONT_COLOR4, ORANGE);
do_once font_color(FONT_COLOR5, CYAN); font_color(FONT_COLOR5, CYAN);
const char *sym = codepoint_to_utf8(cp);
font_goto(x,y);
return font_print(va("%s" FONT_H1 "%s", cp >= ICON_MDI_MIN ? FONT_FACE3 : FONT_FACE2, sym));
} }
vec2 editor_glyphstr(int x, int y, const char *utf8) { font_goto(x,y);
vec2 dim = {x,y}; vec2 pos = {x,y};
const char *sym = codepoint_to_utf8(codepoint);
return add2(pos, font_print(va("%s%s%s", style ? style : "", codepoint >= ICON_MDI_MIN ? FONT_FACE3 : FONT_FACE2, sym)));
}
vec2 editor_glyphs(int x, int y, const char *style, const char *utf8) {
vec2 pos = {x,y};
array(unsigned) codepoints = string32(utf8); array(unsigned) codepoints = string32(utf8);
for( int i = 0, end = array_count(codepoints); i < end; ++i) for( int i = 0, end = array_count(codepoints); i < end; ++i)
add2(dim, editor_glyph(dim.x,dim.y,codepoints[i])); pos = add2(pos, editor_glyph(pos.x,pos.y,style,codepoints[i]));
return dim; return pos;
} }
void editor_frame( void (*game)(unsigned, float, double) ) { void editor_frame( void (*game)(unsigned, float, double) ) {

View File

@ -90,8 +90,8 @@ API vec3 editor_pick(float mouse_x, float mouse_y);
API char* editor_path(const char *path); API char* editor_path(const char *path);
API void editor_setmouse(int x, int y); API void editor_setmouse(int x, int y);
API vec2 editor_glyph(int x, int y, unsigned cp); API vec2 editor_glyph(int x, int y, const char *style, unsigned codepoint);
API vec2 editor_glyphstr(int x, int y, const char *utf8); API vec2 editor_glyphs(int x, int y, const char *style, const char *utf8);
API void editor_gizmos(int dim); API void editor_gizmos(int dim);
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------

View File

@ -1388,6 +1388,7 @@ static const unsigned table_middle_east[] = {
static const unsigned table_emoji[] = { static const unsigned table_emoji[] = {
// 0xE000, 0xEB4C, // Private use (emojis) // 0xE000, 0xEB4C, // Private use (emojis)
0xE000, 0xF8FF, // Private use (emojis+webfonts) 0xE000, 0xF8FF, // Private use (emojis+webfonts)
0xF0001,0xF1CC7,// Private use (icon mdi)
0 0
}; };
@ -1575,6 +1576,7 @@ typedef struct font_t {
unsigned num_glyphs; unsigned num_glyphs;
unsigned *cp2iter; unsigned *cp2iter;
unsigned *iter2cp; unsigned *iter2cp;
unsigned begin; // first glyph. used in cp2iter table to clamp into a lesser range
// font info and data // font info and data
int height; // bitmap height int height; // bitmap height
@ -1671,7 +1673,8 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
if( font_size <= 0 || font_size > 72 ) return; if( font_size <= 0 || font_size > 72 ) return;
if( !ttf_data || !ttf_len ) return; if( !ttf_data || !ttf_len ) return;
flags |= FONT_ASCII; // ensure this minimal range [0020-00FF] is always in if(!(flags & FONT_EM))
flags |= FONT_ASCII; // ensure this minimal range [0020-00FF] is almost always in
font_t *f = &fonts[index]; font_t *f = &fonts[index];
f->initialized = 1; f->initialized = 1;
@ -1731,12 +1734,13 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
// pack and create bitmap // pack and create bitmap
unsigned char *bitmap = (unsigned char*)MALLOC(f->height*f->width); unsigned char *bitmap = (unsigned char*)MALLOC(f->height*f->width);
int charCount = 0xFFFF; int charCount = *array_back(sorted) - sorted[0] + 1; // 0xEFFFF;
f->begin = sorted[0];
f->cdata = (stbtt_packedchar*)CALLOC(1, sizeof(stbtt_packedchar) * charCount); f->cdata = (stbtt_packedchar*)CALLOC(1, sizeof(stbtt_packedchar) * charCount);
f->iter2cp = (unsigned*)CALLOC( 1, sizeof(unsigned) * charCount ); f->iter2cp = (unsigned*)MALLOC( sizeof(unsigned) * charCount );
for( int i = 0; i < charCount; ++i ) f->iter2cp[i] = 0xFFFD; // default invalid glyph f->cp2iter = (unsigned*)MALLOC( sizeof(unsigned) * charCount );
f->cp2iter = (unsigned*)CALLOC( 1, sizeof(unsigned) * charCount ); for( int i = 0; i < charCount; ++i )
for( int i = 0; i < charCount; ++i ) f->cp2iter[i] = 0xFFFD; // default invalid glyph f->iter2cp[i] = f->cp2iter[i] = 0xFFFD; // default invalid glyph
stbtt_pack_context pc; stbtt_pack_context pc;
if( !stbtt_PackBegin(&pc, bitmap, f->width, f->height, 0, 1, NULL) ) { if( !stbtt_PackBegin(&pc, bitmap, f->width, f->height, 0, 1, NULL) ) {
@ -1750,11 +1754,11 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
while( i < (num-1) && (sorted[i+1]-sorted[i]) == 1 ) end = sorted[++i]; while( i < (num-1) && (sorted[i+1]-sorted[i]) == 1 ) end = sorted[++i];
//printf("(%d,%d)", (unsigned)begin, (unsigned)end); //printf("(%d,%d)", (unsigned)begin, (unsigned)end);
if( stbtt_PackFontRange(&pc, ttf_data, 0, f->font_size, begin, end - begin + 1, (stbtt_packedchar*)f->cdata + begin) ) { if( stbtt_PackFontRange(&pc, ttf_data, 0, f->font_size, begin, end - begin + 1, (stbtt_packedchar*)f->cdata + begin - f->begin) ) {
for( int j = begin; j <= end; ++j ) { for( uint64_t cp = begin; cp <= end; ++cp ) {
// unicode->index runtime lookup // unicode->index runtime lookup
f->cp2iter[ j ] = count; f->cp2iter[ cp - f->begin ] = count;
f->iter2cp[ count++ ] = j; f->iter2cp[ count++ ] = cp;
} }
} else { } else {
PRINTF("!Failed to pack atlas font. Likely out of texture mem."); PRINTF("!Failed to pack atlas font. Likely out of texture mem.");
@ -1786,7 +1790,7 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
for (int i = 0; i < f->num_glyphs; i++) { for (int i = 0; i < f->num_glyphs; i++) {
int cp = f->iter2cp[i]; int cp = f->iter2cp[i];
if( cp == 0xFFFD ) continue; if( cp == 0xFFFD ) continue;
stbtt_packedchar *cd = &f->cdata[ cp ]; stbtt_packedchar *cd = &f->cdata[ cp - f->begin ];
if (cd->y1 > max_y1) { if (cd->y1 > max_y1) {
max_y1 = cd->y1; max_y1 = cd->y1;
} }
@ -1853,8 +1857,8 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
unsigned cp = f->iter2cp[ i ]; unsigned cp = f->iter2cp[ i ];
if(cp == 0xFFFD) continue; if(cp == 0xFFFD) continue;
stbtt_packedchar *cd = &f->cdata[ cp ]; stbtt_packedchar *cd = &f->cdata[ cp - f->begin ];
// if(cd->x1==cd->x0) { f->iter2cp[i] = f->cp2iter[cp] = 0xFFFD; continue; } // if(cd->x1==cd->x0) { f->iter2cp[i] = f->cp2iter[cp - f->begin] = 0xFFFD; continue; }
int k1 = 0*f->num_glyphs + count; int k1 = 0*f->num_glyphs + count;
int k2 = 1*f->num_glyphs + count; ++count; int k2 = 1*f->num_glyphs + count; ++count;
@ -2058,7 +2062,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
} }
// convert to vbo data // convert to vbo data
int cp = ch; // f->cp2iter[ch]; int cp = ch - f->begin; // f->cp2iter[ch - f->begin];
//if(cp == 0xFFFD) continue; //if(cp == 0xFFFD) continue;
//if(cp > f->num_glyphs) cp = 0xFFFD; //if(cp > f->num_glyphs) cp = 0xFFFD;

View File

@ -118,6 +118,12 @@ void *gui_userdata() {
return last_skin->userdata; return last_skin->userdata;
} }
vec2 gui_getskinsize(const char *skin) {
vec2 size={0};
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &size);
return size;
}
static static
gui_state_t *gui_getstate(int id) { gui_state_t *gui_getstate(int id) {
if (!ctl_states) map_init(ctl_states, less_int, hash_int); if (!ctl_states) map_init(ctl_states, less_int, hash_int);
@ -142,13 +148,13 @@ bool (gui_button)(int id, vec4 r, const char *skin) {
} }
char *btn = va("%s%s", skin?skin:"button", entry->held?"_press":entry->hover?"_hover":""); char *btn = va("%s%s", skin?skin:"button", entry->held?"_press":entry->hover?"_hover":"");
if (last_skin->draw_rect_func) last_skin->draw_rect_func(last_skin->userdata, btn, r); if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, r);
return was_clicked; return was_clicked;
} }
void (gui_panel)(int id, vec4 r, const char *skin) { void (gui_panel)(int id, vec4 r, const char *skin) {
if (last_skin->draw_rect_func) last_skin->draw_rect_func(last_skin->userdata, skin?skin:"panel", r); if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin?skin:"panel", r);
} }
/* skinned */ /* skinned */
@ -176,15 +182,25 @@ void skinned_draw_missing_rect(vec4 r) {
static static
void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r) { void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r) {
vec4 outer = f->bounds;
r.x -= f->pivot.x*scale;
r.y -= f->pivot.y*scale;
r.z += r.x;
r.w += r.y;
// Ensure dest rectangle is large enough to render the whole element
if ((r.z-r.x) < (outer.z-outer.x) * scale) {
r.z = r.x + (outer.z-outer.x) * scale;
}
if ((r.w-r.y) < (outer.w-outer.y) * scale) {
r.w = r.y + (outer.w-outer.y) * scale;
}
if (!f->has_9slice) { if (!f->has_9slice) {
gui_drawrect(a->tex, v42v2(f->bounds), 0xFFFFFFFF, v42v2(r)); gui_drawrect(a->tex, v42v2(f->bounds), 0xFFFFFFFF, v42v2(r));
return; return;
} }
r.z += r.x;
r.w += r.y;
vec4 outer = f->bounds;
vec4 core = f->core; vec4 core = f->core;
core.x += outer.x; core.x += outer.x;
core.y += outer.y; core.y += outer.y;
@ -204,14 +220,6 @@ void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r
vec4 bottom_middle_slice = {core.x, core.w, core.z, outer.w}; vec4 bottom_middle_slice = {core.x, core.w, core.z, outer.w};
vec4 bottom_right_slice = {core.z, core.w, outer.z, outer.w}; vec4 bottom_right_slice = {core.z, core.w, outer.z, outer.w};
// Ensure dest rectangle is large enough to render the whole element
if ((r.z-r.x) < (outer.z-outer.x) * scale) {
r.z = r.x + (outer.z-outer.x) * scale;
}
if ((r.w-r.y) < (outer.w-outer.y) * scale) {
r.w = r.y + (outer.w-outer.y) * scale;
}
vec4 top_left = {r.x, r.y, r.x + (core.x - outer.x) * scale, r.y + (core.y - outer.y) * scale}; vec4 top_left = {r.x, r.y, r.x + (core.x - outer.x) * scale, r.y + (core.y - outer.y) * scale};
vec4 top_right = {r.z - (outer.z - core.z) * scale, r.y, r.z, r.y + (core.y - outer.y) * scale}; vec4 top_right = {r.z - (outer.z - core.z) * scale, r.y, r.z, r.y + (core.y - outer.y) * scale};
vec4 bottom_left = {r.x, r.w - (outer.w - core.w) * scale, r.x + (core.x - outer.x) * scale, r.w}; vec4 bottom_left = {r.x, r.w - (outer.w - core.w) * scale, r.x + (core.x - outer.x) * scale, r.w};
@ -244,13 +252,24 @@ void skinned_draw_rect(void* userdata, const char *skin, vec4 r) {
else skinned_draw_sprite(a->scale, &a->atlas, f, r); else skinned_draw_sprite(a->scale, &a->atlas, f, r);
} }
void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (f) {
size->x = (f->bounds.z-f->bounds.x)*a->scale;
size->y = (f->bounds.w-f->bounds.y)*a->scale;
}
}
guiskin_t gui_skinned(const char *inifile, float scale) { guiskin_t gui_skinned(const char *inifile, float scale) {
skinned_t *a = REALLOC(0, sizeof(skinned_t)); skinned_t *a = REALLOC(0, sizeof(skinned_t));
a->atlas = atlas_create(inifile, 0); a->atlas = atlas_create(inifile, 0);
a->scale = scale?scale:1.0f; a->scale = scale?scale:1.0f;
guiskin_t skin={0}; guiskin_t skin={0};
skin.userdata = a; skin.userdata = a;
skin.draw_rect_func = skinned_draw_rect; skin.drawrect = skinned_draw_rect;
skin.getskinsize = skinned_getskinsize;
skin.free = skinned_free; skin.free = skinned_free;
return skin; return skin;
} }

View File

@ -2,13 +2,15 @@
// game ui // game ui
typedef struct guiskin_t { typedef struct guiskin_t {
void (*draw_rect_func)(void* userdata, const char *skin, vec4 rect); void (*drawrect)(void* userdata, const char *skin, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
void (*free)(void* userdata); void (*free)(void* userdata);
void *userdata; void *userdata;
} guiskin_t; } guiskin_t;
API void gui_pushskin(guiskin_t skin); API void gui_pushskin(guiskin_t skin);
API void* gui_userdata(); API void* gui_userdata();
API vec2 gui_getskinsize(const char *skin);
// -- // --
API void gui_panel(int id, vec4 rect, const char *skin); API void gui_panel(int id, vec4 rect, const char *skin);
API bool gui_button(int id, vec4 rect, const char *skin); API bool gui_button(int id, vec4 rect, const char *skin);

View File

@ -1277,6 +1277,14 @@ atlas_t atlas_create(const char *inifile, unsigned flags) {
a.slice_frames[index].core = vec4(x,y,x+z,y+w); a.slice_frames[index].core = vec4(x,y,x+z,y+w);
} }
else if ( strend(k, ".sl_pivot") ) {
array_reserve_(a.slice_frames, index);
float x,y;
sscanf(v, "%f,%f", &x, &y);
a.slice_frames[index].pivot = vec2(x,y);
}
else if( strend(k, ".frames") ) { else if( strend(k, ".frames") ) {
array_reserve_(a.anims, index); array_reserve_(a.anims, index);

View File

@ -101,6 +101,7 @@ typedef struct atlas_slice_frame_t {
vec4 bounds; vec4 bounds;
bool has_9slice; bool has_9slice;
vec4 core; vec4 core;
vec2 pivot;
} atlas_slice_frame_t; } atlas_slice_frame_t;
typedef struct atlas_slice_t { typedef struct atlas_slice_t {

View File

@ -10038,6 +10038,7 @@ static const unsigned table_middle_east[] = {
static const unsigned table_emoji[] = { static const unsigned table_emoji[] = {
// 0xE000, 0xEB4C, // Private use (emojis) // 0xE000, 0xEB4C, // Private use (emojis)
0xE000, 0xF8FF, // Private use (emojis+webfonts) 0xE000, 0xF8FF, // Private use (emojis+webfonts)
0xF0001,0xF1CC7,// Private use (icon mdi)
0 0
}; };
@ -10225,6 +10226,7 @@ typedef struct font_t {
unsigned num_glyphs; unsigned num_glyphs;
unsigned *cp2iter; unsigned *cp2iter;
unsigned *iter2cp; unsigned *iter2cp;
unsigned begin; // first glyph. used in cp2iter table to clamp into a lesser range
// font info and data // font info and data
int height; // bitmap height int height; // bitmap height
@ -10321,7 +10323,8 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
if( font_size <= 0 || font_size > 72 ) return; if( font_size <= 0 || font_size > 72 ) return;
if( !ttf_data || !ttf_len ) return; if( !ttf_data || !ttf_len ) return;
flags |= FONT_ASCII; // ensure this minimal range [0020-00FF] is always in if(!(flags & FONT_EM))
flags |= FONT_ASCII; // ensure this minimal range [0020-00FF] is almost always in
font_t *f = &fonts[index]; font_t *f = &fonts[index];
f->initialized = 1; f->initialized = 1;
@ -10381,12 +10384,13 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
// pack and create bitmap // pack and create bitmap
unsigned char *bitmap = (unsigned char*)MALLOC(f->height*f->width); unsigned char *bitmap = (unsigned char*)MALLOC(f->height*f->width);
int charCount = 0xFFFF; int charCount = *array_back(sorted) - sorted[0] + 1; // 0xEFFFF;
f->begin = sorted[0];
f->cdata = (stbtt_packedchar*)CALLOC(1, sizeof(stbtt_packedchar) * charCount); f->cdata = (stbtt_packedchar*)CALLOC(1, sizeof(stbtt_packedchar) * charCount);
f->iter2cp = (unsigned*)CALLOC( 1, sizeof(unsigned) * charCount ); f->iter2cp = (unsigned*)MALLOC( sizeof(unsigned) * charCount );
for( int i = 0; i < charCount; ++i ) f->iter2cp[i] = 0xFFFD; // default invalid glyph f->cp2iter = (unsigned*)MALLOC( sizeof(unsigned) * charCount );
f->cp2iter = (unsigned*)CALLOC( 1, sizeof(unsigned) * charCount ); for( int i = 0; i < charCount; ++i )
for( int i = 0; i < charCount; ++i ) f->cp2iter[i] = 0xFFFD; // default invalid glyph f->iter2cp[i] = f->cp2iter[i] = 0xFFFD; // default invalid glyph
stbtt_pack_context pc; stbtt_pack_context pc;
if( !stbtt_PackBegin(&pc, bitmap, f->width, f->height, 0, 1, NULL) ) { if( !stbtt_PackBegin(&pc, bitmap, f->width, f->height, 0, 1, NULL) ) {
@ -10400,11 +10404,11 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
while( i < (num-1) && (sorted[i+1]-sorted[i]) == 1 ) end = sorted[++i]; while( i < (num-1) && (sorted[i+1]-sorted[i]) == 1 ) end = sorted[++i];
//printf("(%d,%d)", (unsigned)begin, (unsigned)end); //printf("(%d,%d)", (unsigned)begin, (unsigned)end);
if( stbtt_PackFontRange(&pc, ttf_data, 0, f->font_size, begin, end - begin + 1, (stbtt_packedchar*)f->cdata + begin) ) { if( stbtt_PackFontRange(&pc, ttf_data, 0, f->font_size, begin, end - begin + 1, (stbtt_packedchar*)f->cdata + begin - f->begin) ) {
for( int j = begin; j <= end; ++j ) { for( uint64_t cp = begin; cp <= end; ++cp ) {
// unicode->index runtime lookup // unicode->index runtime lookup
f->cp2iter[ j ] = count; f->cp2iter[ cp - f->begin ] = count;
f->iter2cp[ count++ ] = j; f->iter2cp[ count++ ] = cp;
} }
} else { } else {
PRINTF("!Failed to pack atlas font. Likely out of texture mem."); PRINTF("!Failed to pack atlas font. Likely out of texture mem.");
@ -10436,7 +10440,7 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
for (int i = 0; i < f->num_glyphs; i++) { for (int i = 0; i < f->num_glyphs; i++) {
int cp = f->iter2cp[i]; int cp = f->iter2cp[i];
if( cp == 0xFFFD ) continue; if( cp == 0xFFFD ) continue;
stbtt_packedchar *cd = &f->cdata[ cp ]; stbtt_packedchar *cd = &f->cdata[ cp - f->begin ];
if (cd->y1 > max_y1) { if (cd->y1 > max_y1) {
max_y1 = cd->y1; max_y1 = cd->y1;
} }
@ -10503,8 +10507,8 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
unsigned cp = f->iter2cp[ i ]; unsigned cp = f->iter2cp[ i ];
if(cp == 0xFFFD) continue; if(cp == 0xFFFD) continue;
stbtt_packedchar *cd = &f->cdata[ cp ]; stbtt_packedchar *cd = &f->cdata[ cp - f->begin ];
// if(cd->x1==cd->x0) { f->iter2cp[i] = f->cp2iter[cp] = 0xFFFD; continue; } // if(cd->x1==cd->x0) { f->iter2cp[i] = f->cp2iter[cp - f->begin] = 0xFFFD; continue; }
int k1 = 0*f->num_glyphs + count; int k1 = 0*f->num_glyphs + count;
int k2 = 1*f->num_glyphs + count; ++count; int k2 = 1*f->num_glyphs + count; ++count;
@ -10708,7 +10712,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
} }
// convert to vbo data // convert to vbo data
int cp = ch; // f->cp2iter[ch]; int cp = ch - f->begin; // f->cp2iter[ch - f->begin];
//if(cp == 0xFFFD) continue; //if(cp == 0xFFFD) continue;
//if(cp > f->num_glyphs) cp = 0xFFFD; //if(cp > f->num_glyphs) cp = 0xFFFD;
@ -11124,6 +11128,12 @@ void *gui_userdata() {
return last_skin->userdata; return last_skin->userdata;
} }
vec2 gui_getskinsize(const char *skin) {
vec2 size={0};
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &size);
return size;
}
static static
gui_state_t *gui_getstate(int id) { gui_state_t *gui_getstate(int id) {
if (!ctl_states) map_init(ctl_states, less_int, hash_int); if (!ctl_states) map_init(ctl_states, less_int, hash_int);
@ -11148,13 +11158,13 @@ bool (gui_button)(int id, vec4 r, const char *skin) {
} }
char *btn = va("%s%s", skin?skin:"button", entry->held?"_press":entry->hover?"_hover":""); char *btn = va("%s%s", skin?skin:"button", entry->held?"_press":entry->hover?"_hover":"");
if (last_skin->draw_rect_func) last_skin->draw_rect_func(last_skin->userdata, btn, r); if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, r);
return was_clicked; return was_clicked;
} }
void (gui_panel)(int id, vec4 r, const char *skin) { void (gui_panel)(int id, vec4 r, const char *skin) {
if (last_skin->draw_rect_func) last_skin->draw_rect_func(last_skin->userdata, skin?skin:"panel", r); if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin?skin:"panel", r);
} }
/* skinned */ /* skinned */
@ -11182,15 +11192,25 @@ void skinned_draw_missing_rect(vec4 r) {
static static
void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r) { void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r) {
vec4 outer = f->bounds;
r.x -= f->pivot.x*scale;
r.y -= f->pivot.y*scale;
r.z += r.x;
r.w += r.y;
// Ensure dest rectangle is large enough to render the whole element
if ((r.z-r.x) < (outer.z-outer.x) * scale) {
r.z = r.x + (outer.z-outer.x) * scale;
}
if ((r.w-r.y) < (outer.w-outer.y) * scale) {
r.w = r.y + (outer.w-outer.y) * scale;
}
if (!f->has_9slice) { if (!f->has_9slice) {
gui_drawrect(a->tex, v42v2(f->bounds), 0xFFFFFFFF, v42v2(r)); gui_drawrect(a->tex, v42v2(f->bounds), 0xFFFFFFFF, v42v2(r));
return; return;
} }
r.z += r.x;
r.w += r.y;
vec4 outer = f->bounds;
vec4 core = f->core; vec4 core = f->core;
core.x += outer.x; core.x += outer.x;
core.y += outer.y; core.y += outer.y;
@ -11210,14 +11230,6 @@ void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r
vec4 bottom_middle_slice = {core.x, core.w, core.z, outer.w}; vec4 bottom_middle_slice = {core.x, core.w, core.z, outer.w};
vec4 bottom_right_slice = {core.z, core.w, outer.z, outer.w}; vec4 bottom_right_slice = {core.z, core.w, outer.z, outer.w};
// Ensure dest rectangle is large enough to render the whole element
if ((r.z-r.x) < (outer.z-outer.x) * scale) {
r.z = r.x + (outer.z-outer.x) * scale;
}
if ((r.w-r.y) < (outer.w-outer.y) * scale) {
r.w = r.y + (outer.w-outer.y) * scale;
}
vec4 top_left = {r.x, r.y, r.x + (core.x - outer.x) * scale, r.y + (core.y - outer.y) * scale}; vec4 top_left = {r.x, r.y, r.x + (core.x - outer.x) * scale, r.y + (core.y - outer.y) * scale};
vec4 top_right = {r.z - (outer.z - core.z) * scale, r.y, r.z, r.y + (core.y - outer.y) * scale}; vec4 top_right = {r.z - (outer.z - core.z) * scale, r.y, r.z, r.y + (core.y - outer.y) * scale};
vec4 bottom_left = {r.x, r.w - (outer.w - core.w) * scale, r.x + (core.x - outer.x) * scale, r.w}; vec4 bottom_left = {r.x, r.w - (outer.w - core.w) * scale, r.x + (core.x - outer.x) * scale, r.w};
@ -11250,13 +11262,24 @@ void skinned_draw_rect(void* userdata, const char *skin, vec4 r) {
else skinned_draw_sprite(a->scale, &a->atlas, f, r); else skinned_draw_sprite(a->scale, &a->atlas, f, r);
} }
void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (f) {
size->x = (f->bounds.z-f->bounds.x)*a->scale;
size->y = (f->bounds.w-f->bounds.y)*a->scale;
}
}
guiskin_t gui_skinned(const char *inifile, float scale) { guiskin_t gui_skinned(const char *inifile, float scale) {
skinned_t *a = REALLOC(0, sizeof(skinned_t)); skinned_t *a = REALLOC(0, sizeof(skinned_t));
a->atlas = atlas_create(inifile, 0); a->atlas = atlas_create(inifile, 0);
a->scale = scale?scale:1.0f; a->scale = scale?scale:1.0f;
guiskin_t skin={0}; guiskin_t skin={0};
skin.userdata = a; skin.userdata = a;
skin.draw_rect_func = skinned_draw_rect; skin.drawrect = skinned_draw_rect;
skin.getskinsize = skinned_getskinsize;
skin.free = skinned_free; skin.free = skinned_free;
return skin; return skin;
} }
@ -23216,6 +23239,14 @@ atlas_t atlas_create(const char *inifile, unsigned flags) {
a.slice_frames[index].core = vec4(x,y,x+z,y+w); a.slice_frames[index].core = vec4(x,y,x+z,y+w);
} }
else if ( strend(k, ".sl_pivot") ) {
array_reserve_(a.slice_frames, index);
float x,y;
sscanf(v, "%f,%f", &x, &y);
a.slice_frames[index].pivot = vec2(x,y);
}
else if( strend(k, ".frames") ) { else if( strend(k, ".frames") ) {
array_reserve_(a.anims, index); array_reserve_(a.anims, index);
@ -29325,27 +29356,31 @@ void editor_setmouse(int x, int y) {
glfwSetCursorPos( window_handle(), x, y ); glfwSetCursorPos( window_handle(), x, y );
} }
vec2 editor_glyph(int x, int y, unsigned cp) { vec2 editor_glyph(int x, int y, const char *style, unsigned codepoint) {
do_once {
// style: atlas size, unicode ranges and 6 font faces max // style: atlas size, unicode ranges and 6 font faces max
do_once font_face(FONT_FACE2, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048); font_face(FONT_FACE2, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048);
do_once font_face(FONT_FACE3, "materialdesignicons-webfont.ttf", 24.f, FONT_EM|FONT_2048); // {0xF68C /*ICON_MDI_MIN*/, 0xF1CC7/*ICON_MDI_MAX*/, 0}}, font_face(FONT_FACE3, "materialdesignicons-webfont.ttf", 24.f, FONT_EM|FONT_2048); // {0xF68C /*ICON_MDI_MIN*/, 0xF1CC7/*ICON_MDI_MAX*/, 0}},
// style: 10 colors max // style: 10 colors max
do_once font_color(FONT_COLOR1, WHITE); font_color(FONT_COLOR1, WHITE);
do_once font_color(FONT_COLOR2, RGBX(0xE8F1FF,128)); // GRAY); font_color(FONT_COLOR2, RGBX(0xE8F1FF,128)); // GRAY);
do_once font_color(FONT_COLOR3, YELLOW); font_color(FONT_COLOR3, YELLOW);
do_once font_color(FONT_COLOR4, ORANGE); font_color(FONT_COLOR4, ORANGE);
do_once font_color(FONT_COLOR5, CYAN); font_color(FONT_COLOR5, CYAN);
const char *sym = codepoint_to_utf8(cp);
font_goto(x,y);
return font_print(va("%s" FONT_H1 "%s", cp >= ICON_MDI_MIN ? FONT_FACE3 : FONT_FACE2, sym));
} }
vec2 editor_glyphstr(int x, int y, const char *utf8) { font_goto(x,y);
vec2 dim = {x,y}; vec2 pos = {x,y};
const char *sym = codepoint_to_utf8(codepoint);
return add2(pos, font_print(va("%s%s%s", style ? style : "", codepoint >= ICON_MDI_MIN ? FONT_FACE3 : FONT_FACE2, sym)));
}
vec2 editor_glyphs(int x, int y, const char *style, const char *utf8) {
vec2 pos = {x,y};
array(unsigned) codepoints = string32(utf8); array(unsigned) codepoints = string32(utf8);
for( int i = 0, end = array_count(codepoints); i < end; ++i) for( int i = 0, end = array_count(codepoints); i < end; ++i)
add2(dim, editor_glyph(dim.x,dim.y,codepoints[i])); pos = add2(pos, editor_glyph(pos.x,pos.y,style,codepoints[i]));
return dim; return pos;
} }
void editor_frame( void (*game)(unsigned, float, double) ) { void editor_frame( void (*game)(unsigned, float, double) ) {

View File

@ -4123,6 +4123,7 @@ typedef struct atlas_slice_frame_t {
vec4 bounds; vec4 bounds;
bool has_9slice; bool has_9slice;
vec4 core; vec4 core;
vec2 pivot;
} atlas_slice_frame_t; } atlas_slice_frame_t;
typedef struct atlas_slice_t { typedef struct atlas_slice_t {
@ -4183,13 +4184,15 @@ API void sprite_setanim(sprite_t *s, unsigned name);
// game ui // game ui
typedef struct guiskin_t { typedef struct guiskin_t {
void (*draw_rect_func)(void* userdata, const char *skin, vec4 rect); void (*drawrect)(void* userdata, const char *skin, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
void (*free)(void* userdata); void (*free)(void* userdata);
void *userdata; void *userdata;
} guiskin_t; } guiskin_t;
API void gui_pushskin(guiskin_t skin); API void gui_pushskin(guiskin_t skin);
API void* gui_userdata(); API void* gui_userdata();
API vec2 gui_getskinsize(const char *skin);
// -- // --
API void gui_panel(int id, vec4 rect, const char *skin); API void gui_panel(int id, vec4 rect, const char *skin);
API bool gui_button(int id, vec4 rect, const char *skin); API bool gui_button(int id, vec4 rect, const char *skin);
@ -4791,8 +4794,8 @@ API vec3 editor_pick(float mouse_x, float mouse_y);
API char* editor_path(const char *path); API char* editor_path(const char *path);
API void editor_setmouse(int x, int y); API void editor_setmouse(int x, int y);
API vec2 editor_glyph(int x, int y, unsigned cp); API vec2 editor_glyph(int x, int y, const char *style, unsigned codepoint);
API vec2 editor_glyphstr(int x, int y, const char *utf8); API vec2 editor_glyphs(int x, int y, const char *style, const char *utf8);
API void editor_gizmos(int dim); API void editor_gizmos(int dim);
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------

Binary file not shown.

BIN
tools/ase2ini.lib 100644

Binary file not shown.

Binary file not shown.

Binary file not shown.