implement sliders and panels

main
Dominik Madarász 2023-11-28 14:31:56 +01:00
parent cbe002f8e8
commit 31acdce47d
11 changed files with 528 additions and 77 deletions

View File

@ -149,7 +149,7 @@ if "%1"=="git" (
call make.bat bind
rem call make.bat docs
call make.bat amalgamation
rem call make.bat amalgamation
rem call make.bat split
rem rd /q /s engine\split
@ -229,7 +229,7 @@ if "%1"=="push" (
)
if "%1"=="prep" (
call make.bat join
call make.bat split
call make.bat amalgamation
exit /b
)
@ -311,7 +311,8 @@ if "%1"=="vps" (
if "%1"=="fwk" (
pushd ..\fwk-mirror
call MAKE.bat sync
git fetch
git reset --hard origin/main
popd
call MAKE.bat fwk_prep
start "" fwk_diff.WinMerge
@ -319,6 +320,7 @@ if "%1"=="fwk" (
)
if "%1"=="fwk_prep" (
call make.bat split
if not exist "_fwk" mkdir "_fwk"
if not exist "_fwk\demos" mkdir "_fwk\demos"
if not exist "_fwk\tools" mkdir "_fwk\tools"
@ -419,6 +421,9 @@ if "%1"=="back" (
rem tools\fwkren.exe tools\cook.ini to
call make.bat join
call make.bat amalgamation
echo All done.
endlocal
exit /b

View File

@ -1522,15 +1522,27 @@ ffi.cdef([[
//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 (*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] vec4: macro name but used as C declaration in:void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
//lcpp INF [0000] vec4: macro name but used as C declaration in:bool (*ismouseinrect)(void* userdata, const char *skin, vec4 rect);
//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: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:API bool gui_button(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC bool gui_button(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in: bool gui_button(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in:API bool gui_ismouseinrect(const char *skin, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC bool gui_ismouseinrect(const char *skin, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in: bool gui_ismouseinrect(const char *skin, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in:API void gui_panel_id(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC void gui_panel_id(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in: void gui_panel_id(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in:API void gui_rect_id(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC void gui_rect_id(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in: void gui_rect_id(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in:API bool gui_button_id(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC bool gui_button_id(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in: bool gui_button_id(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in:API bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, float step, float *value);
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, float step, float *value);
//lcpp INF [0000] vec4: macro name but used as C declaration in: bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, float step, float *value);
//lcpp INF [0000] test: macro name but used as C declaration in:API int (test)(const char *file, int line, const char *expr, bool result);
//lcpp INF [0000] test: macro name but used as C declaration in:STATIC int (test)(const char *file, int line, const char *expr, bool result);
//lcpp INF [0000] test: macro name but used as C declaration in: int (test)(const char *file, int line, const char *expr, bool result);
@ -3306,14 +3318,20 @@ enum { OBJTYPE_sprite_t = 10 }; typedef struct { unsigned static_assert_on
typedef struct guiskin_t {
void (*drawrect)(void* userdata, const char *skin, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
bool (*ismouseinrect)(void* userdata, const char *skin, vec4 rect);
void (*free)(void* userdata);
void *userdata;
} guiskin_t;
void gui_pushskin(guiskin_t skin);
void* gui_userdata();
vec2 gui_getskinsize(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_ismouseinrect(const char *skin, vec4 rect);
void gui_panel_id(int id, vec4 rect, const char *skin);
void gui_rect_id(int id, vec4 rect, const char *skin);
bool gui_button_id(int id, vec4 rect, const char *skin);
bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, float step, float *value);
void gui_panel_end();
void gui_popskin();
typedef struct skinned_t {
atlas_t atlas;

View File

@ -8,6 +8,9 @@ int main() {
vec4 pos = vec4(400,400,100, 30);
float testval=7.5f;
float testval2=7.5f;
while( window_swap() && !input(KEY_ESC) ) { // game loop
vec4 panel_pos = vec4(0, 0, window_width(), window_height());
@ -32,21 +35,26 @@ int main() {
}
//
gui_panel(panel_pos, 0);
if (gui_button(pos, 0)) {
printf("%s\n", "Button pressed!");
}
gui_panel(panel_pos, "panel");
if (gui_button(pos, 0)) {
printf("%s\n", "Button pressed!");
}
gui_panel(vec4(40,140, 320, 20*skinned->scale), "vial");
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_rect(vec4(40,140, 320, 20*skinned->scale), "vial");
gui_rect(vec4(40,140, 200, 14*skinned->scale), "hp");
gui_rect(vec4(40,240, 240, 20*skinned->scale), "vial");
gui_rect(vec4(40,240, 160, 14*skinned->scale), "mp");
vec2 badge_size = gui_getskinsize("badge");
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");
vec2 badge_size = gui_getskinsize("badge");
badge_size.x += 2; // padding
gui_rect(vec4(60+badge_size.x*0,320, 1, 1), "badge");
gui_rect(vec4(60+badge_size.x*1,320, 1, 1), "badge");
gui_rect(vec4(60+badge_size.x*2,320, 1, 1), "badge_empty");
vec2 slider_size = gui_getskinsize("slider");
gui_slider(vec4(60, 480, 80*skinned->scale, 1), 0, 0.0f, 15.0f, 1.0f, &testval);
gui_slider(vec4(60, 480+slider_size.y+10, 120*skinned->scale, 1), 0, -5.0f, 20.0f, 0.0f, &testval2);
gui_panel_end();
}
gui_popskin();

Binary file not shown.

View File

@ -18119,6 +18119,8 @@ API void sprite_setanim(sprite_t *s, unsigned name);
typedef struct guiskin_t {
void (*drawrect)(void* userdata, const char *skin, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
bool (*ismouseinrect)(void* userdata, const char *skin, vec4 rect);
void (*free)(void* userdata);
void *userdata;
} guiskin_t;
@ -18126,14 +18128,20 @@ typedef struct guiskin_t {
API void gui_pushskin(guiskin_t skin);
API void* gui_userdata();
API vec2 gui_getskinsize(const char *skin);
API bool gui_ismouseinrect(const char *skin, vec4 rect);
// --
API void gui_panel(int id, vec4 rect, const char *skin);
API bool gui_button(int id, vec4 rect, const char *skin);
API void gui_panel_id(int id, vec4 rect, const char *skin);
API void gui_rect_id(int id, vec4 rect, const char *skin);
API bool gui_button_id(int id, vec4 rect, const char *skin);
API bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, float step, float *value);
API void gui_panel_end();
API void gui_popskin();
// helpers
#define gui_panel(...) gui_panel(__LINE__, __VA_ARGS__)
#define gui_button(...) gui_button(__LINE__, __VA_ARGS__)
#define gui_panel(...) gui_panel_id(__LINE__, __VA_ARGS__)
#define gui_rect(...) gui_rect_id(__LINE__, __VA_ARGS__)
#define gui_button(...) gui_button_id(__LINE__, __VA_ARGS__)
#define gui_slider(...) gui_slider_id(__LINE__, __VA_ARGS__)
// default renderers
@ -358926,18 +358934,17 @@ void gui_drawrect( texture_t texture, vec2 tex_start, vec2 tex_end, int rgba, ve
// ----------------------------------------------------------------------------
// game ui
typedef struct gui_state_t {
union {
struct {
bool held;
bool hover;
};
typedef union gui_state_t {
struct {
bool held;
bool hover;
};
} gui_state_t;
static __thread array(guiskin_t) skins=0;
static __thread guiskin_t *last_skin=0;
static __thread map(int, gui_state_t) ctl_states=0; //@leak
static __thread array(vec4) scissor_rects=0;
void gui_pushskin(guiskin_t skin) {
array_push(skins, skin);
@ -358961,18 +358968,46 @@ vec2 gui_getskinsize(const char *skin) {
return size;
}
bool gui_ismouseinrect(const char *skin, vec4 rect) {
if (last_skin->ismouseinrect) return last_skin->ismouseinrect(last_skin->userdata, skin, rect);
return false;
}
static
gui_state_t *gui_getstate(int id) {
if (!ctl_states) map_init(ctl_states, less_int, hash_int);
return map_find_or_add(ctl_states, id, (gui_state_t){0});
}
bool (gui_button)(int id, vec4 r, const char *skin) {
void gui_panel_id(int id, vec4 rect, const char *skin) {
(void)id;
vec4 scissor={0, 0, window_width(), window_height()};
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &scissor);
if (!array_count(scissor_rects))
glEnable(GL_SCISSOR_TEST);
glScissor(scissor.x, scissor.y, scissor.z, scissor.w);
array_push(scissor_rects, scissor);
}
void gui_panel_end() {
ASSERT(array_count(scissor_rects));
array_pop(scissor_rects);
if (array_count(scissor_rects)) {
vec4 scissor = *array_back(scissor_rects);
glScissor(scissor.x, scissor.y, scissor.z, scissor.w);
} else {
glDisable(GL_SCISSOR_TEST);
}
}
bool gui_button_id(int id, vec4 r, const char *skin) {
gui_state_t *entry = gui_getstate(id);
bool was_clicked=0;
entry->hover = false;
if (input(MOUSE_X) > r.x && input(MOUSE_X) < (r.x+r.z) && input(MOUSE_Y) > r.y && input(MOUSE_Y) < (r.y+r.w)) {
char *btn = va("%s%s", skin?skin:"button", entry->held?"_press":entry->hover?"_hover":"");
if (gui_ismouseinrect(btn, r)) {
if (input_up(MOUSE_L) && entry->held) {
was_clicked=1;
}
@ -358983,15 +359018,74 @@ bool (gui_button)(int id, vec4 r, const char *skin) {
else if (input_up(MOUSE_L) && entry->held) {
entry->held = false;
}
else {
entry->hover = false;
}
char *btn = va("%s%s", skin?skin:"button", entry->held?"_press":entry->hover?"_hover":"");
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, r);
return was_clicked;
}
void (gui_panel)(int id, vec4 r, const char *skin) {
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin?skin:"panel", r);
static
float slider2posx(float min, float max, float value, float step, float w) {
float norm = value - min;
float range = max - min;
float rel = norm / range;
float res = w * rel;
return step==0.0f?res:(round(res/step)*step);
}
static
float posx2slider(vec4 rect, float min, float max, float xpos, float step) {
xpos = clampf(xpos, rect.x, rect.x+rect.z);
double rel = (xpos - rect.x) / rect.z;
float res = min + (rel * (max - min));
return step==0.0f?res:(round(res/step)*step);
}
bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, float step, float *value) {
gui_state_t *entry = gui_getstate(id);
skin = skin?skin:"slider";
char *cursorskin = va("%s_cursor%s", skin, entry->held?"_press":entry->hover?"_hover":"");
if (gui_ismouseinrect(skin, rect)) {
entry->held = input_held(MOUSE_L);
entry->hover = true;
}
else if (input_up(MOUSE_L) && entry->held) {
entry->held = false;
}
else {
entry->hover = false;
}
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
vec2 slidersize={0}, cursorsize={0};
vec4 usablerect=rect;
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &usablerect);
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &slidersize);
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, cursorskin, &cursorsize);
if (entry->held) {
*value = posx2slider(usablerect, min, max, input(MOUSE_X), step);
}
float sliderx = slider2posx(min, max, *value, step, usablerect.z);
vec2 cursorpos = vec2(sliderx+usablerect.x*.5f-cursorsize.x*.5f, (slidersize.y*.5f - cursorsize.y*.5f));
vec4 cursorrect = rect;
cursorrect.x += cursorpos.x;
cursorrect.y += cursorpos.y;
cursorrect.z = cursorsize.x;
cursorrect.w = cursorsize.y;
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, cursorskin, cursorrect);
return false;
}
void gui_rect_id(int id, vec4 r, const char *skin) {
(void)id;
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, r);
}
/* skinned */
@ -359008,6 +359102,7 @@ atlas_slice_frame_t *skinned_getsliceframe(atlas_t *a, const char *name) {
for (int i = 0; i < array_count(a->slices); i++)
if (!strcmp(quark_string(&a->db, a->slices[i].name), name))
return &a->slice_frames[a->slices[i].frames[0]];
PRINTF("slice name: '%s' is missing in atlas!\n", name);
return NULL;
}
@ -359017,6 +359112,28 @@ void skinned_draw_missing_rect(vec4 r) {
gui_drawrect(texture_checker(), v42v2(size), 0x800080FF, v42v2(r));
}
static
bool skinned_ismouseinrect(void *userdata, const char *skin, vec4 r) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f) return false;
vec4 outer = f->bounds;
r.x -= f->pivot.x*a->scale;
r.y -= f->pivot.y*a->scale;
r.z += r.x;
r.w += r.y;
if ((r.z-r.x) < (outer.z-outer.x) * a->scale) {
r.z = r.x + (outer.z-outer.x) * a->scale;
}
if ((r.w-r.y) < (outer.w-outer.y) * a->scale) {
r.w = r.y + (outer.w-outer.y) * a->scale;
}
return (input(MOUSE_X) > r.x && input(MOUSE_X) < r.z && input(MOUSE_Y) > r.y && input(MOUSE_Y) < r.w);
}
static
void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r) {
vec4 outer = f->bounds;
@ -359099,6 +359216,27 @@ void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
}
}
static
void skinned_getscissorrect(void* userdata, const char *skin, vec4 rect, vec4 *dims) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f) return;
*dims = rect;
if (!f->has_9slice) return;
vec2 skinsize, coresize;
skinsize.x = (f->bounds.z-f->bounds.x)*a->scale;
skinsize.y = (f->bounds.w-f->bounds.y)*a->scale;
coresize.x = (f->core.z-f->core.x)*a->scale;
coresize.y = (f->core.w-f->core.y)*a->scale;
dims->x += f->core.x*a->scale;
dims->y += f->core.y*a->scale;
dims->z -= (skinsize.x - coresize.x);
dims->w -= (skinsize.y - coresize.y);
}
guiskin_t gui_skinned(const char *inifile, float scale) {
skinned_t *a = REALLOC(0, sizeof(skinned_t));
a->atlas = atlas_create(inifile, 0);
@ -359107,6 +359245,8 @@ guiskin_t gui_skinned(const char *inifile, float scale) {
skin.userdata = a;
skin.drawrect = skinned_draw_rect;
skin.getskinsize = skinned_getskinsize;
skin.ismouseinrect = skinned_ismouseinrect;
skin.getscissorrect = skinned_getscissorrect;
skin.free = skinned_free;
return skin;
}

View File

@ -89,18 +89,17 @@ void gui_drawrect( texture_t texture, vec2 tex_start, vec2 tex_end, int rgba, ve
// ----------------------------------------------------------------------------
// game ui
typedef struct gui_state_t {
union {
struct {
bool held;
bool hover;
};
typedef union gui_state_t {
struct {
bool held;
bool hover;
};
} gui_state_t;
static __thread array(guiskin_t) skins=0;
static __thread guiskin_t *last_skin=0;
static __thread map(int, gui_state_t) ctl_states=0; //@leak
static __thread array(vec4) scissor_rects=0;
void gui_pushskin(guiskin_t skin) {
array_push(skins, skin);
@ -124,18 +123,46 @@ vec2 gui_getskinsize(const char *skin) {
return size;
}
bool gui_ismouseinrect(const char *skin, vec4 rect) {
if (last_skin->ismouseinrect) return last_skin->ismouseinrect(last_skin->userdata, skin, rect);
return false;
}
static
gui_state_t *gui_getstate(int id) {
if (!ctl_states) map_init(ctl_states, less_int, hash_int);
return map_find_or_add(ctl_states, id, (gui_state_t){0});
}
bool (gui_button)(int id, vec4 r, const char *skin) {
void gui_panel_id(int id, vec4 rect, const char *skin) {
(void)id;
vec4 scissor={0, 0, window_width(), window_height()};
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &scissor);
if (!array_count(scissor_rects))
glEnable(GL_SCISSOR_TEST);
glScissor(scissor.x, scissor.y, scissor.z, scissor.w);
array_push(scissor_rects, scissor);
}
void gui_panel_end() {
ASSERT(array_count(scissor_rects));
array_pop(scissor_rects);
if (array_count(scissor_rects)) {
vec4 scissor = *array_back(scissor_rects);
glScissor(scissor.x, scissor.y, scissor.z, scissor.w);
} else {
glDisable(GL_SCISSOR_TEST);
}
}
bool gui_button_id(int id, vec4 r, const char *skin) {
gui_state_t *entry = gui_getstate(id);
bool was_clicked=0;
entry->hover = false;
if (input(MOUSE_X) > r.x && input(MOUSE_X) < (r.x+r.z) && input(MOUSE_Y) > r.y && input(MOUSE_Y) < (r.y+r.w)) {
char *btn = va("%s%s", skin?skin:"button", entry->held?"_press":entry->hover?"_hover":"");
if (gui_ismouseinrect(btn, r)) {
if (input_up(MOUSE_L) && entry->held) {
was_clicked=1;
}
@ -146,15 +173,74 @@ bool (gui_button)(int id, vec4 r, const char *skin) {
else if (input_up(MOUSE_L) && entry->held) {
entry->held = false;
}
else {
entry->hover = false;
}
char *btn = va("%s%s", skin?skin:"button", entry->held?"_press":entry->hover?"_hover":"");
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, r);
return was_clicked;
}
void (gui_panel)(int id, vec4 r, const char *skin) {
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin?skin:"panel", r);
static
float slider2posx(float min, float max, float value, float step, float w) {
float norm = value - min;
float range = max - min;
float rel = norm / range;
float res = w * rel;
return step==0.0f?res:(round(res/step)*step);
}
static
float posx2slider(vec4 rect, float min, float max, float xpos, float step) {
xpos = clampf(xpos, rect.x, rect.x+rect.z);
double rel = (xpos - rect.x) / rect.z;
float res = min + (rel * (max - min));
return step==0.0f?res:(round(res/step)*step);
}
bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, float step, float *value) {
gui_state_t *entry = gui_getstate(id);
skin = skin?skin:"slider";
char *cursorskin = va("%s_cursor%s", skin, entry->held?"_press":entry->hover?"_hover":"");
if (gui_ismouseinrect(skin, rect)) {
entry->held = input_held(MOUSE_L);
entry->hover = true;
}
else if (input_up(MOUSE_L) && entry->held) {
entry->held = false;
}
else {
entry->hover = false;
}
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
vec2 slidersize={0}, cursorsize={0};
vec4 usablerect=rect;
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &usablerect);
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &slidersize);
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, cursorskin, &cursorsize);
if (entry->held) {
*value = posx2slider(usablerect, min, max, input(MOUSE_X), step);
}
float sliderx = slider2posx(min, max, *value, step, usablerect.z);
vec2 cursorpos = vec2(sliderx+usablerect.x*.5f-cursorsize.x*.5f, (slidersize.y*.5f - cursorsize.y*.5f));
vec4 cursorrect = rect;
cursorrect.x += cursorpos.x;
cursorrect.y += cursorpos.y;
cursorrect.z = cursorsize.x;
cursorrect.w = cursorsize.y;
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, cursorskin, cursorrect);
return false;
}
void gui_rect_id(int id, vec4 r, const char *skin) {
(void)id;
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, r);
}
/* skinned */
@ -171,6 +257,7 @@ atlas_slice_frame_t *skinned_getsliceframe(atlas_t *a, const char *name) {
for (int i = 0; i < array_count(a->slices); i++)
if (!strcmp(quark_string(&a->db, a->slices[i].name), name))
return &a->slice_frames[a->slices[i].frames[0]];
PRINTF("slice name: '%s' is missing in atlas!\n", name);
return NULL;
}
@ -180,6 +267,28 @@ void skinned_draw_missing_rect(vec4 r) {
gui_drawrect(texture_checker(), v42v2(size), 0x800080FF, v42v2(r));
}
static
bool skinned_ismouseinrect(void *userdata, const char *skin, vec4 r) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f) return false;
vec4 outer = f->bounds;
r.x -= f->pivot.x*a->scale;
r.y -= f->pivot.y*a->scale;
r.z += r.x;
r.w += r.y;
if ((r.z-r.x) < (outer.z-outer.x) * a->scale) {
r.z = r.x + (outer.z-outer.x) * a->scale;
}
if ((r.w-r.y) < (outer.w-outer.y) * a->scale) {
r.w = r.y + (outer.w-outer.y) * a->scale;
}
return (input(MOUSE_X) > r.x && input(MOUSE_X) < r.z && input(MOUSE_Y) > r.y && input(MOUSE_Y) < r.w);
}
static
void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r) {
vec4 outer = f->bounds;
@ -262,6 +371,27 @@ void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
}
}
static
void skinned_getscissorrect(void* userdata, const char *skin, vec4 rect, vec4 *dims) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f) return;
*dims = rect;
if (!f->has_9slice) return;
vec2 skinsize, coresize;
skinsize.x = (f->bounds.z-f->bounds.x)*a->scale;
skinsize.y = (f->bounds.w-f->bounds.y)*a->scale;
coresize.x = (f->core.z-f->core.x)*a->scale;
coresize.y = (f->core.w-f->core.y)*a->scale;
dims->x += f->core.x*a->scale;
dims->y += f->core.y*a->scale;
dims->z -= (skinsize.x - coresize.x);
dims->w -= (skinsize.y - coresize.y);
}
guiskin_t gui_skinned(const char *inifile, float scale) {
skinned_t *a = REALLOC(0, sizeof(skinned_t));
a->atlas = atlas_create(inifile, 0);
@ -270,6 +400,8 @@ guiskin_t gui_skinned(const char *inifile, float scale) {
skin.userdata = a;
skin.drawrect = skinned_draw_rect;
skin.getskinsize = skinned_getskinsize;
skin.ismouseinrect = skinned_ismouseinrect;
skin.getscissorrect = skinned_getscissorrect;
skin.free = skinned_free;
return skin;
}

View File

@ -4,6 +4,8 @@
typedef struct guiskin_t {
void (*drawrect)(void* userdata, const char *skin, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
bool (*ismouseinrect)(void* userdata, const char *skin, vec4 rect);
void (*free)(void* userdata);
void *userdata;
} guiskin_t;
@ -11,14 +13,20 @@ typedef struct guiskin_t {
API void gui_pushskin(guiskin_t skin);
API void* gui_userdata();
API vec2 gui_getskinsize(const char *skin);
API bool gui_ismouseinrect(const char *skin, vec4 rect);
// --
API void gui_panel(int id, vec4 rect, const char *skin);
API bool gui_button(int id, vec4 rect, const char *skin);
API void gui_panel_id(int id, vec4 rect, const char *skin);
API void gui_rect_id(int id, vec4 rect, const char *skin);
API bool gui_button_id(int id, vec4 rect, const char *skin);
API bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, float step, float *value);
API void gui_panel_end();
API void gui_popskin();
// helpers
#define gui_panel(...) gui_panel(__LINE__, __VA_ARGS__)
#define gui_button(...) gui_button(__LINE__, __VA_ARGS__)
#define gui_panel(...) gui_panel_id(__LINE__, __VA_ARGS__)
#define gui_rect(...) gui_rect_id(__LINE__, __VA_ARGS__)
#define gui_button(...) gui_button_id(__LINE__, __VA_ARGS__)
#define gui_slider(...) gui_slider_id(__LINE__, __VA_ARGS__)
// default renderers

View File

@ -11099,18 +11099,17 @@ void gui_drawrect( texture_t texture, vec2 tex_start, vec2 tex_end, int rgba, ve
// ----------------------------------------------------------------------------
// game ui
typedef struct gui_state_t {
union {
struct {
bool held;
bool hover;
};
typedef union gui_state_t {
struct {
bool held;
bool hover;
};
} gui_state_t;
static __thread array(guiskin_t) skins=0;
static __thread guiskin_t *last_skin=0;
static __thread map(int, gui_state_t) ctl_states=0; //@leak
static __thread array(vec4) scissor_rects=0;
void gui_pushskin(guiskin_t skin) {
array_push(skins, skin);
@ -11134,18 +11133,46 @@ vec2 gui_getskinsize(const char *skin) {
return size;
}
bool gui_ismouseinrect(const char *skin, vec4 rect) {
if (last_skin->ismouseinrect) return last_skin->ismouseinrect(last_skin->userdata, skin, rect);
return false;
}
static
gui_state_t *gui_getstate(int id) {
if (!ctl_states) map_init(ctl_states, less_int, hash_int);
return map_find_or_add(ctl_states, id, (gui_state_t){0});
}
bool (gui_button)(int id, vec4 r, const char *skin) {
void gui_panel_id(int id, vec4 rect, const char *skin) {
(void)id;
vec4 scissor={0, 0, window_width(), window_height()};
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &scissor);
if (!array_count(scissor_rects))
glEnable(GL_SCISSOR_TEST);
glScissor(scissor.x, scissor.y, scissor.z, scissor.w);
array_push(scissor_rects, scissor);
}
void gui_panel_end() {
ASSERT(array_count(scissor_rects));
array_pop(scissor_rects);
if (array_count(scissor_rects)) {
vec4 scissor = *array_back(scissor_rects);
glScissor(scissor.x, scissor.y, scissor.z, scissor.w);
} else {
glDisable(GL_SCISSOR_TEST);
}
}
bool gui_button_id(int id, vec4 r, const char *skin) {
gui_state_t *entry = gui_getstate(id);
bool was_clicked=0;
entry->hover = false;
if (input(MOUSE_X) > r.x && input(MOUSE_X) < (r.x+r.z) && input(MOUSE_Y) > r.y && input(MOUSE_Y) < (r.y+r.w)) {
char *btn = va("%s%s", skin?skin:"button", entry->held?"_press":entry->hover?"_hover":"");
if (gui_ismouseinrect(btn, r)) {
if (input_up(MOUSE_L) && entry->held) {
was_clicked=1;
}
@ -11156,15 +11183,74 @@ bool (gui_button)(int id, vec4 r, const char *skin) {
else if (input_up(MOUSE_L) && entry->held) {
entry->held = false;
}
else {
entry->hover = false;
}
char *btn = va("%s%s", skin?skin:"button", entry->held?"_press":entry->hover?"_hover":"");
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, r);
return was_clicked;
}
void (gui_panel)(int id, vec4 r, const char *skin) {
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin?skin:"panel", r);
static
float slider2posx(float min, float max, float value, float step, float w) {
float norm = value - min;
float range = max - min;
float rel = norm / range;
float res = w * rel;
return step==0.0f?res:(round(res/step)*step);
}
static
float posx2slider(vec4 rect, float min, float max, float xpos, float step) {
xpos = clampf(xpos, rect.x, rect.x+rect.z);
double rel = (xpos - rect.x) / rect.z;
float res = min + (rel * (max - min));
return step==0.0f?res:(round(res/step)*step);
}
bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, float step, float *value) {
gui_state_t *entry = gui_getstate(id);
skin = skin?skin:"slider";
char *cursorskin = va("%s_cursor%s", skin, entry->held?"_press":entry->hover?"_hover":"");
if (gui_ismouseinrect(skin, rect)) {
entry->held = input_held(MOUSE_L);
entry->hover = true;
}
else if (input_up(MOUSE_L) && entry->held) {
entry->held = false;
}
else {
entry->hover = false;
}
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
vec2 slidersize={0}, cursorsize={0};
vec4 usablerect=rect;
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &usablerect);
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &slidersize);
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, cursorskin, &cursorsize);
if (entry->held) {
*value = posx2slider(usablerect, min, max, input(MOUSE_X), step);
}
float sliderx = slider2posx(min, max, *value, step, usablerect.z);
vec2 cursorpos = vec2(sliderx+usablerect.x*.5f-cursorsize.x*.5f, (slidersize.y*.5f - cursorsize.y*.5f));
vec4 cursorrect = rect;
cursorrect.x += cursorpos.x;
cursorrect.y += cursorpos.y;
cursorrect.z = cursorsize.x;
cursorrect.w = cursorsize.y;
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, cursorskin, cursorrect);
return false;
}
void gui_rect_id(int id, vec4 r, const char *skin) {
(void)id;
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, r);
}
/* skinned */
@ -11181,6 +11267,7 @@ atlas_slice_frame_t *skinned_getsliceframe(atlas_t *a, const char *name) {
for (int i = 0; i < array_count(a->slices); i++)
if (!strcmp(quark_string(&a->db, a->slices[i].name), name))
return &a->slice_frames[a->slices[i].frames[0]];
PRINTF("slice name: '%s' is missing in atlas!\n", name);
return NULL;
}
@ -11190,6 +11277,28 @@ void skinned_draw_missing_rect(vec4 r) {
gui_drawrect(texture_checker(), v42v2(size), 0x800080FF, v42v2(r));
}
static
bool skinned_ismouseinrect(void *userdata, const char *skin, vec4 r) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f) return false;
vec4 outer = f->bounds;
r.x -= f->pivot.x*a->scale;
r.y -= f->pivot.y*a->scale;
r.z += r.x;
r.w += r.y;
if ((r.z-r.x) < (outer.z-outer.x) * a->scale) {
r.z = r.x + (outer.z-outer.x) * a->scale;
}
if ((r.w-r.y) < (outer.w-outer.y) * a->scale) {
r.w = r.y + (outer.w-outer.y) * a->scale;
}
return (input(MOUSE_X) > r.x && input(MOUSE_X) < r.z && input(MOUSE_Y) > r.y && input(MOUSE_Y) < r.w);
}
static
void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r) {
vec4 outer = f->bounds;
@ -11272,6 +11381,27 @@ void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
}
}
static
void skinned_getscissorrect(void* userdata, const char *skin, vec4 rect, vec4 *dims) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f) return;
*dims = rect;
if (!f->has_9slice) return;
vec2 skinsize, coresize;
skinsize.x = (f->bounds.z-f->bounds.x)*a->scale;
skinsize.y = (f->bounds.w-f->bounds.y)*a->scale;
coresize.x = (f->core.z-f->core.x)*a->scale;
coresize.y = (f->core.w-f->core.y)*a->scale;
dims->x += f->core.x*a->scale;
dims->y += f->core.y*a->scale;
dims->z -= (skinsize.x - coresize.x);
dims->w -= (skinsize.y - coresize.y);
}
guiskin_t gui_skinned(const char *inifile, float scale) {
skinned_t *a = REALLOC(0, sizeof(skinned_t));
a->atlas = atlas_create(inifile, 0);
@ -11280,6 +11410,8 @@ guiskin_t gui_skinned(const char *inifile, float scale) {
skin.userdata = a;
skin.drawrect = skinned_draw_rect;
skin.getskinsize = skinned_getskinsize;
skin.ismouseinrect = skinned_ismouseinrect;
skin.getscissorrect = skinned_getscissorrect;
skin.free = skinned_free;
return skin;
}

View File

@ -4186,6 +4186,8 @@ API void sprite_setanim(sprite_t *s, unsigned name);
typedef struct guiskin_t {
void (*drawrect)(void* userdata, const char *skin, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
bool (*ismouseinrect)(void* userdata, const char *skin, vec4 rect);
void (*free)(void* userdata);
void *userdata;
} guiskin_t;
@ -4193,14 +4195,20 @@ typedef struct guiskin_t {
API void gui_pushskin(guiskin_t skin);
API void* gui_userdata();
API vec2 gui_getskinsize(const char *skin);
API bool gui_ismouseinrect(const char *skin, vec4 rect);
// --
API void gui_panel(int id, vec4 rect, const char *skin);
API bool gui_button(int id, vec4 rect, const char *skin);
API void gui_panel_id(int id, vec4 rect, const char *skin);
API void gui_rect_id(int id, vec4 rect, const char *skin);
API bool gui_button_id(int id, vec4 rect, const char *skin);
API bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, float step, float *value);
API void gui_panel_end();
API void gui_popskin();
// helpers
#define gui_panel(...) gui_panel(__LINE__, __VA_ARGS__)
#define gui_button(...) gui_button(__LINE__, __VA_ARGS__)
#define gui_panel(...) gui_panel_id(__LINE__, __VA_ARGS__)
#define gui_rect(...) gui_rect_id(__LINE__, __VA_ARGS__)
#define gui_button(...) gui_button_id(__LINE__, __VA_ARGS__)
#define gui_slider(...) gui_slider_id(__LINE__, __VA_ARGS__)
// default renderers

View File

@ -25,9 +25,9 @@ ART=../demos/art/,../engine/art/,../editor/art/ ; comma-separated folder(s) tha
; also, once a symbol is found, it is replaced by its value always.
; some predefined symbols: INPUT (input filename), OUTPUT (output filename), PRETTY (clean input filename), PROGRESS (cook progress).
@windows `echo Cooking PROGRESS% PRETTY...`
@linux `echo "Cooking PROGRESS% PRETTY..."`
@osx `echo "Cooking PROGRESS% PRETTY..."`
;@windows `echo Cooking PROGRESS% PRETTY...`
;@linux `echo "Cooking PROGRESS% PRETTY..."`
;@osx `echo "Cooking PROGRESS% PRETTY..."`
; ------------------------------------------------------------------------------
; groups below are collection of files that we want to cook, and then package.

View File

@ -3,8 +3,8 @@
[
{
"path": ".",
"file_exclude_patterns": ["*.exe.manifest", "*.zip", "*.ilk", "*.exp", "_mirror/", "engine/v4k*", "engine/joint/"],
"index_exclude_patterns": ["engine/joint/v4k.h", "engine/v4k.h", "engine/v4k.c", "_mirror/**"]
"file_exclude_patterns": ["*.exe.manifest", "*.zip", "*.ilk", "*.exp", "_mirror/", "engine/v4k", "engine/joint/", "engine/split/"],
"index_exclude_patterns": ["engine/joint/v4k.h", "engine/split/**", "_mirror/**"]
}
],
"settings": {