implement sliders and panels
parent
cbe002f8e8
commit
31acdce47d
11
MAKE.bat
11
MAKE.bat
|
@ -149,7 +149,7 @@ if "%1"=="git" (
|
||||||
call make.bat bind
|
call make.bat bind
|
||||||
rem call make.bat docs
|
rem call make.bat docs
|
||||||
|
|
||||||
call make.bat amalgamation
|
rem call make.bat amalgamation
|
||||||
rem call make.bat split
|
rem call make.bat split
|
||||||
|
|
||||||
rem rd /q /s engine\split
|
rem rd /q /s engine\split
|
||||||
|
@ -229,7 +229,7 @@ if "%1"=="push" (
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1"=="prep" (
|
if "%1"=="prep" (
|
||||||
call make.bat join
|
call make.bat split
|
||||||
call make.bat amalgamation
|
call make.bat amalgamation
|
||||||
exit /b
|
exit /b
|
||||||
)
|
)
|
||||||
|
@ -311,7 +311,8 @@ if "%1"=="vps" (
|
||||||
|
|
||||||
if "%1"=="fwk" (
|
if "%1"=="fwk" (
|
||||||
pushd ..\fwk-mirror
|
pushd ..\fwk-mirror
|
||||||
call MAKE.bat sync
|
git fetch
|
||||||
|
git reset --hard origin/main
|
||||||
popd
|
popd
|
||||||
call MAKE.bat fwk_prep
|
call MAKE.bat fwk_prep
|
||||||
start "" fwk_diff.WinMerge
|
start "" fwk_diff.WinMerge
|
||||||
|
@ -319,6 +320,7 @@ if "%1"=="fwk" (
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1"=="fwk_prep" (
|
if "%1"=="fwk_prep" (
|
||||||
|
call make.bat split
|
||||||
if not exist "_fwk" mkdir "_fwk"
|
if not exist "_fwk" mkdir "_fwk"
|
||||||
if not exist "_fwk\demos" mkdir "_fwk\demos"
|
if not exist "_fwk\demos" mkdir "_fwk\demos"
|
||||||
if not exist "_fwk\tools" mkdir "_fwk\tools"
|
if not exist "_fwk\tools" mkdir "_fwk\tools"
|
||||||
|
@ -419,6 +421,9 @@ if "%1"=="back" (
|
||||||
|
|
||||||
rem tools\fwkren.exe tools\cook.ini to
|
rem tools\fwkren.exe tools\cook.ini to
|
||||||
|
|
||||||
|
call make.bat join
|
||||||
|
call make.bat amalgamation
|
||||||
|
|
||||||
echo All done.
|
echo All done.
|
||||||
endlocal
|
endlocal
|
||||||
exit /b
|
exit /b
|
||||||
|
|
34
bind/v4k.lua
34
bind/v4k.lua
|
@ -1522,15 +1522,27 @@ ffi.cdef([[
|
||||||
//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 (*drawrect)(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: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: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: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] 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 bool gui_ismouseinrect(const char *skin, vec4 rect);
|
||||||
//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 bool gui_ismouseinrect(const char *skin, vec4 rect);
|
||||||
//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: bool gui_ismouseinrect(const char *skin, vec4 rect);
|
||||||
//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: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 bool gui_button(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: bool gui_button(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: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: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);
|
//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 {
|
typedef struct guiskin_t {
|
||||||
void (*drawrect)(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 (*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 (*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);
|
vec2 gui_getskinsize(const char *skin);
|
||||||
void gui_panel(int id, vec4 rect, const char *skin);
|
bool gui_ismouseinrect(const char *skin, vec4 rect);
|
||||||
bool gui_button(int id, vec4 rect, const char *skin);
|
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();
|
void gui_popskin();
|
||||||
typedef struct skinned_t {
|
typedef struct skinned_t {
|
||||||
atlas_t atlas;
|
atlas_t atlas;
|
||||||
|
|
|
@ -8,6 +8,9 @@ int main() {
|
||||||
|
|
||||||
vec4 pos = vec4(400,400,100, 30);
|
vec4 pos = vec4(400,400,100, 30);
|
||||||
|
|
||||||
|
float testval=7.5f;
|
||||||
|
float testval2=7.5f;
|
||||||
|
|
||||||
while( window_swap() && !input(KEY_ESC) ) { // game loop
|
while( window_swap() && !input(KEY_ESC) ) { // game loop
|
||||||
vec4 panel_pos = vec4(0, 0, window_width(), window_height());
|
vec4 panel_pos = vec4(0, 0, window_width(), window_height());
|
||||||
|
|
||||||
|
@ -32,21 +35,26 @@ int main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
gui_panel(panel_pos, 0);
|
gui_panel(panel_pos, "panel");
|
||||||
if (gui_button(pos, 0)) {
|
if (gui_button(pos, 0)) {
|
||||||
printf("%s\n", "Button pressed!");
|
printf("%s\n", "Button pressed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
gui_panel(vec4(40,140, 320, 20*skinned->scale), "vial");
|
gui_rect(vec4(40,140, 320, 20*skinned->scale), "vial");
|
||||||
gui_panel(vec4(40,140, 200, 14*skinned->scale), "hp");
|
gui_rect(vec4(40,140, 200, 14*skinned->scale), "hp");
|
||||||
gui_panel(vec4(40,240, 240, 20*skinned->scale), "vial");
|
gui_rect(vec4(40,240, 240, 20*skinned->scale), "vial");
|
||||||
gui_panel(vec4(40,240, 160, 14*skinned->scale), "mp");
|
gui_rect(vec4(40,240, 160, 14*skinned->scale), "mp");
|
||||||
|
|
||||||
vec2 badge_size = gui_getskinsize("badge");
|
vec2 badge_size = gui_getskinsize("badge");
|
||||||
badge_size.x += 2; // padding
|
badge_size.x += 2; // padding
|
||||||
gui_panel(vec4(60+badge_size.x*0,320, 1, 1), "badge");
|
gui_rect(vec4(60+badge_size.x*0,320, 1, 1), "badge");
|
||||||
gui_panel(vec4(60+badge_size.x*1,320, 1, 1), "badge");
|
gui_rect(vec4(60+badge_size.x*1,320, 1, 1), "badge");
|
||||||
gui_panel(vec4(60+badge_size.x*2,320, 1, 1), "badge_empty");
|
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();
|
gui_popskin();
|
||||||
|
|
Binary file not shown.
|
@ -18119,6 +18119,8 @@ API void sprite_setanim(sprite_t *s, unsigned name);
|
||||||
typedef struct guiskin_t {
|
typedef struct guiskin_t {
|
||||||
void (*drawrect)(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 (*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 (*free)(void* userdata);
|
||||||
void *userdata;
|
void *userdata;
|
||||||
} guiskin_t;
|
} guiskin_t;
|
||||||
|
@ -18126,14 +18128,20 @@ typedef struct 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 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 void gui_panel_id(int id, vec4 rect, const char *skin);
|
||||||
API bool gui_button(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();
|
API void gui_popskin();
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
#define gui_panel(...) gui_panel(__LINE__, __VA_ARGS__)
|
#define gui_panel(...) gui_panel_id(__LINE__, __VA_ARGS__)
|
||||||
#define gui_button(...) gui_button(__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
|
// default renderers
|
||||||
|
|
||||||
|
@ -358926,18 +358934,17 @@ void gui_drawrect( texture_t texture, vec2 tex_start, vec2 tex_end, int rgba, ve
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// game ui
|
// game ui
|
||||||
|
|
||||||
typedef struct gui_state_t {
|
typedef union gui_state_t {
|
||||||
union {
|
|
||||||
struct {
|
struct {
|
||||||
bool held;
|
bool held;
|
||||||
bool hover;
|
bool hover;
|
||||||
};
|
};
|
||||||
};
|
|
||||||
} gui_state_t;
|
} gui_state_t;
|
||||||
|
|
||||||
static __thread array(guiskin_t) skins=0;
|
static __thread array(guiskin_t) skins=0;
|
||||||
static __thread guiskin_t *last_skin=0;
|
static __thread guiskin_t *last_skin=0;
|
||||||
static __thread map(int, gui_state_t) ctl_states=0; //@leak
|
static __thread map(int, gui_state_t) ctl_states=0; //@leak
|
||||||
|
static __thread array(vec4) scissor_rects=0;
|
||||||
|
|
||||||
void gui_pushskin(guiskin_t skin) {
|
void gui_pushskin(guiskin_t skin) {
|
||||||
array_push(skins, skin);
|
array_push(skins, skin);
|
||||||
|
@ -358961,18 +358968,46 @@ vec2 gui_getskinsize(const char *skin) {
|
||||||
return size;
|
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
|
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);
|
||||||
return map_find_or_add(ctl_states, id, (gui_state_t){0});
|
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);
|
gui_state_t *entry = gui_getstate(id);
|
||||||
bool was_clicked=0;
|
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) {
|
if (input_up(MOUSE_L) && entry->held) {
|
||||||
was_clicked=1;
|
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) {
|
else if (input_up(MOUSE_L) && entry->held) {
|
||||||
entry->held = false;
|
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);
|
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) {
|
static
|
||||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin?skin:"panel", r);
|
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 */
|
/* 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++)
|
for (int i = 0; i < array_count(a->slices); i++)
|
||||||
if (!strcmp(quark_string(&a->db, a->slices[i].name), name))
|
if (!strcmp(quark_string(&a->db, a->slices[i].name), name))
|
||||||
return &a->slice_frames[a->slices[i].frames[0]];
|
return &a->slice_frames[a->slices[i].frames[0]];
|
||||||
|
PRINTF("slice name: '%s' is missing in atlas!\n", name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359017,6 +359112,28 @@ void skinned_draw_missing_rect(vec4 r) {
|
||||||
gui_drawrect(texture_checker(), v42v2(size), 0x800080FF, v42v2(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
|
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;
|
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) {
|
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);
|
||||||
|
@ -359107,6 +359245,8 @@ guiskin_t gui_skinned(const char *inifile, float scale) {
|
||||||
skin.userdata = a;
|
skin.userdata = a;
|
||||||
skin.drawrect = skinned_draw_rect;
|
skin.drawrect = skinned_draw_rect;
|
||||||
skin.getskinsize = skinned_getskinsize;
|
skin.getskinsize = skinned_getskinsize;
|
||||||
|
skin.ismouseinrect = skinned_ismouseinrect;
|
||||||
|
skin.getscissorrect = skinned_getscissorrect;
|
||||||
skin.free = skinned_free;
|
skin.free = skinned_free;
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,18 +89,17 @@ void gui_drawrect( texture_t texture, vec2 tex_start, vec2 tex_end, int rgba, ve
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// game ui
|
// game ui
|
||||||
|
|
||||||
typedef struct gui_state_t {
|
typedef union gui_state_t {
|
||||||
union {
|
|
||||||
struct {
|
struct {
|
||||||
bool held;
|
bool held;
|
||||||
bool hover;
|
bool hover;
|
||||||
};
|
};
|
||||||
};
|
|
||||||
} gui_state_t;
|
} gui_state_t;
|
||||||
|
|
||||||
static __thread array(guiskin_t) skins=0;
|
static __thread array(guiskin_t) skins=0;
|
||||||
static __thread guiskin_t *last_skin=0;
|
static __thread guiskin_t *last_skin=0;
|
||||||
static __thread map(int, gui_state_t) ctl_states=0; //@leak
|
static __thread map(int, gui_state_t) ctl_states=0; //@leak
|
||||||
|
static __thread array(vec4) scissor_rects=0;
|
||||||
|
|
||||||
void gui_pushskin(guiskin_t skin) {
|
void gui_pushskin(guiskin_t skin) {
|
||||||
array_push(skins, skin);
|
array_push(skins, skin);
|
||||||
|
@ -124,18 +123,46 @@ vec2 gui_getskinsize(const char *skin) {
|
||||||
return size;
|
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
|
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);
|
||||||
return map_find_or_add(ctl_states, id, (gui_state_t){0});
|
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);
|
gui_state_t *entry = gui_getstate(id);
|
||||||
bool was_clicked=0;
|
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) {
|
if (input_up(MOUSE_L) && entry->held) {
|
||||||
was_clicked=1;
|
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) {
|
else if (input_up(MOUSE_L) && entry->held) {
|
||||||
entry->held = false;
|
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);
|
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) {
|
static
|
||||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin?skin:"panel", r);
|
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 */
|
/* 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++)
|
for (int i = 0; i < array_count(a->slices); i++)
|
||||||
if (!strcmp(quark_string(&a->db, a->slices[i].name), name))
|
if (!strcmp(quark_string(&a->db, a->slices[i].name), name))
|
||||||
return &a->slice_frames[a->slices[i].frames[0]];
|
return &a->slice_frames[a->slices[i].frames[0]];
|
||||||
|
PRINTF("slice name: '%s' is missing in atlas!\n", name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,6 +267,28 @@ void skinned_draw_missing_rect(vec4 r) {
|
||||||
gui_drawrect(texture_checker(), v42v2(size), 0x800080FF, v42v2(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
|
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;
|
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) {
|
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);
|
||||||
|
@ -270,6 +400,8 @@ guiskin_t gui_skinned(const char *inifile, float scale) {
|
||||||
skin.userdata = a;
|
skin.userdata = a;
|
||||||
skin.drawrect = skinned_draw_rect;
|
skin.drawrect = skinned_draw_rect;
|
||||||
skin.getskinsize = skinned_getskinsize;
|
skin.getskinsize = skinned_getskinsize;
|
||||||
|
skin.ismouseinrect = skinned_ismouseinrect;
|
||||||
|
skin.getscissorrect = skinned_getscissorrect;
|
||||||
skin.free = skinned_free;
|
skin.free = skinned_free;
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
typedef struct guiskin_t {
|
typedef struct guiskin_t {
|
||||||
void (*drawrect)(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 (*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 (*free)(void* userdata);
|
||||||
void *userdata;
|
void *userdata;
|
||||||
} guiskin_t;
|
} guiskin_t;
|
||||||
|
@ -11,14 +13,20 @@ typedef struct 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 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 void gui_panel_id(int id, vec4 rect, const char *skin);
|
||||||
API bool gui_button(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();
|
API void gui_popskin();
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
#define gui_panel(...) gui_panel(__LINE__, __VA_ARGS__)
|
#define gui_panel(...) gui_panel_id(__LINE__, __VA_ARGS__)
|
||||||
#define gui_button(...) gui_button(__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
|
// default renderers
|
||||||
|
|
||||||
|
|
150
engine/v4k.c
150
engine/v4k.c
|
@ -11099,18 +11099,17 @@ void gui_drawrect( texture_t texture, vec2 tex_start, vec2 tex_end, int rgba, ve
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// game ui
|
// game ui
|
||||||
|
|
||||||
typedef struct gui_state_t {
|
typedef union gui_state_t {
|
||||||
union {
|
|
||||||
struct {
|
struct {
|
||||||
bool held;
|
bool held;
|
||||||
bool hover;
|
bool hover;
|
||||||
};
|
};
|
||||||
};
|
|
||||||
} gui_state_t;
|
} gui_state_t;
|
||||||
|
|
||||||
static __thread array(guiskin_t) skins=0;
|
static __thread array(guiskin_t) skins=0;
|
||||||
static __thread guiskin_t *last_skin=0;
|
static __thread guiskin_t *last_skin=0;
|
||||||
static __thread map(int, gui_state_t) ctl_states=0; //@leak
|
static __thread map(int, gui_state_t) ctl_states=0; //@leak
|
||||||
|
static __thread array(vec4) scissor_rects=0;
|
||||||
|
|
||||||
void gui_pushskin(guiskin_t skin) {
|
void gui_pushskin(guiskin_t skin) {
|
||||||
array_push(skins, skin);
|
array_push(skins, skin);
|
||||||
|
@ -11134,18 +11133,46 @@ vec2 gui_getskinsize(const char *skin) {
|
||||||
return size;
|
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
|
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);
|
||||||
return map_find_or_add(ctl_states, id, (gui_state_t){0});
|
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);
|
gui_state_t *entry = gui_getstate(id);
|
||||||
bool was_clicked=0;
|
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) {
|
if (input_up(MOUSE_L) && entry->held) {
|
||||||
was_clicked=1;
|
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) {
|
else if (input_up(MOUSE_L) && entry->held) {
|
||||||
entry->held = false;
|
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);
|
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) {
|
static
|
||||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin?skin:"panel", r);
|
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 */
|
/* 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++)
|
for (int i = 0; i < array_count(a->slices); i++)
|
||||||
if (!strcmp(quark_string(&a->db, a->slices[i].name), name))
|
if (!strcmp(quark_string(&a->db, a->slices[i].name), name))
|
||||||
return &a->slice_frames[a->slices[i].frames[0]];
|
return &a->slice_frames[a->slices[i].frames[0]];
|
||||||
|
PRINTF("slice name: '%s' is missing in atlas!\n", name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11190,6 +11277,28 @@ void skinned_draw_missing_rect(vec4 r) {
|
||||||
gui_drawrect(texture_checker(), v42v2(size), 0x800080FF, v42v2(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
|
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;
|
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) {
|
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);
|
||||||
|
@ -11280,6 +11410,8 @@ guiskin_t gui_skinned(const char *inifile, float scale) {
|
||||||
skin.userdata = a;
|
skin.userdata = a;
|
||||||
skin.drawrect = skinned_draw_rect;
|
skin.drawrect = skinned_draw_rect;
|
||||||
skin.getskinsize = skinned_getskinsize;
|
skin.getskinsize = skinned_getskinsize;
|
||||||
|
skin.ismouseinrect = skinned_ismouseinrect;
|
||||||
|
skin.getscissorrect = skinned_getscissorrect;
|
||||||
skin.free = skinned_free;
|
skin.free = skinned_free;
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
|
16
engine/v4k.h
16
engine/v4k.h
|
@ -4186,6 +4186,8 @@ API void sprite_setanim(sprite_t *s, unsigned name);
|
||||||
typedef struct guiskin_t {
|
typedef struct guiskin_t {
|
||||||
void (*drawrect)(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 (*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 (*free)(void* userdata);
|
||||||
void *userdata;
|
void *userdata;
|
||||||
} guiskin_t;
|
} guiskin_t;
|
||||||
|
@ -4193,14 +4195,20 @@ typedef struct 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 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 void gui_panel_id(int id, vec4 rect, const char *skin);
|
||||||
API bool gui_button(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();
|
API void gui_popskin();
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
#define gui_panel(...) gui_panel(__LINE__, __VA_ARGS__)
|
#define gui_panel(...) gui_panel_id(__LINE__, __VA_ARGS__)
|
||||||
#define gui_button(...) gui_button(__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
|
// default renderers
|
||||||
|
|
||||||
|
|
|
@ -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.
|
; 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).
|
; some predefined symbols: INPUT (input filename), OUTPUT (output filename), PRETTY (clean input filename), PROGRESS (cook progress).
|
||||||
|
|
||||||
@windows `echo Cooking PROGRESS% PRETTY...`
|
;@windows `echo Cooking PROGRESS% PRETTY...`
|
||||||
@linux `echo "Cooking PROGRESS% PRETTY..."`
|
;@linux `echo "Cooking PROGRESS% PRETTY..."`
|
||||||
@osx `echo "Cooking PROGRESS% PRETTY..."`
|
;@osx `echo "Cooking PROGRESS% PRETTY..."`
|
||||||
|
|
||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
; groups below are collection of files that we want to cook, and then package.
|
; groups below are collection of files that we want to cook, and then package.
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"path": ".",
|
"path": ".",
|
||||||
"file_exclude_patterns": ["*.exe.manifest", "*.zip", "*.ilk", "*.exp", "_mirror/", "engine/v4k*", "engine/joint/"],
|
"file_exclude_patterns": ["*.exe.manifest", "*.zip", "*.ilk", "*.exp", "_mirror/", "engine/v4k", "engine/joint/", "engine/split/"],
|
||||||
"index_exclude_patterns": ["engine/joint/v4k.h", "engine/v4k.h", "engine/v4k.c", "_mirror/**"]
|
"index_exclude_patterns": ["engine/joint/v4k.h", "engine/split/**", "_mirror/**"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
|
|
Loading…
Reference in New Issue