Archived
1
0
Fork 0
This repository has been archived on 2025-09-02. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
skcblitz/gui.h
2025-09-02 14:43:36 +02:00

2252 lines
83 KiB
C

byte gui_inside(gui_t *elem, int x, int y) {
return (x >= elem->pos_x) && (x < (elem->pos_x + elem->size_x)) && (y >= elem->pos_y) && (y < (elem->pos_y + elem->size_y));
}
gui_t *gui_clicked(window_t *win, int x, int y) {
if(win->selected && win->selected->visible && (win->selected->type == GUI_DROPDOWN_HANDLE) && gui_inside(win->selected, x, y))
return win->selected; // fix (?)
for(int z = 0; z < win->n_elems; z++) {
gui_t *elem = &win->elems[z];
if(elem->visible && elem->enabled && gui_inside(elem, x, y)) {
return elem;
}
}
return NULL;
}
uint gui_darken_color(uint color, float factor) {
return (color & 0xff000000) | ((uint)((float)((color >> 16) & 0xff) * factor) << 16) | ((uint)((float)((color >> 8) & 0xff) * factor) << 8) |
(uint)((float)(color & 0xff) * factor);
}
gui_t *gui_set_style(gui_t *elem, byte type, byte border) {
if(elem->type != GUI_SLIDER && elem->precision == 0xff)
return elem;
type = elem->type != GUI_SLIDER && elem->precision ? elem->precision : type;
border = elem->type != GUI_SLIDER && elem->precision ? (elem->border ? 0 : 2) | (border & 1) : border;
uint top = (type == GUI_LABEL) ? 0 : ((type == GUI_FIELD) ? sys.style.field_top : (type == GUI_CUSTOM ? ((elem->window->focused ^ (elem->type == GUI_TOGGLE_ON)) ? sys.style.win_top : sys.style.win_btm) :
sys.style.fill_top));
uint bottom = (type == GUI_LABEL) ? 0 : ((type == GUI_FIELD) ? sys.style.field_btm : (type == GUI_CUSTOM ? ((elem->window->focused ^ (elem->type == GUI_TOGGLE_ON)) ? sys.style.win_btm : sys.style.win_top) :
sys.style.fill_btm));
elem->color_fill_t = (type == GUI_TOGGLE_ON || type == GUI_SLIDER) ? bottom : top;
elem->color_fill_b = (type == GUI_TOGGLE_ON || type == GUI_SLIDER) ? top : bottom;
elem->color_brdr_t = (border & 2) ? 0 : (type == GUI_CUSTOM ? sys.style.wbrdr_top : sys.style.brdr_top);
elem->color_brdr_b = (border & 2) ? 0 : (type == GUI_CUSTOM ? sys.style.wbrdr_btm : sys.style.brdr_btm);
elem->color_text = (type == GUI_CUSTOM ? sys.style.text_win : (elem->type == GUI_LABEL ? sys.style.text_label :
(elem->type == GUI_FIELD ? sys.style.text_field : sys.style.text_base)));
if((type == GUI_CUSTOM && !elem->window->focused) || (type == GUI_TOGGLE_OFF))
elem->color_text = gui_darken_color(elem->color_text, 0.8f);
if(border & 1)
elem->border = (border & 2) ? 0 : sys.style.border;
if(elem->type != GUI_SLIDER && type != elem->type)
elem->precision = type;
return elem;
}
gui_t *gui_update_style(gui_t *elem, byte border) {
if(elem->type == GUI_CUSTOM)
return elem;
gui_set_style(elem, elem->type, (elem->type == GUI_LABEL ? 2 : 0) | border);
if(elem->type == GUI_SLIDER) {
elem->margin_x1 = (int)sys.style.fill_top;
elem->margin_y1 = (int)sys.style.fill_btm;
elem->margin_x2 = (int)sys.style.brdr_btm;
elem->margin_y2 = (int)sys.style.brdr_top;
if(border) {
elem->sel_end = ((elem->size_y * sys.style.slider_width) / 24) & ~1;
elem->sel_drag = sys.style.border;
}
}
// else {
// elem->margin_x1 = elem->margin_x2 = (elem->type == GUI_FIELD || elem->type == GUI_DROPDOWN_HANDLE) ? elem->border : 0;
// elem->margin_y1 = elem->margin_y2 = (elem->type == GUI_FIELD || elem->type == GUI_DROPDOWN_HANDLE) ? elem->border : 0;
// }
if(elem->visible)
elem->r_dirty = 1;
return elem;
}
gui_t *gui_add_elem(window_t *win, int x, int y, int w, int h, byte type) {
gui_t *elem = &win->elems[win->n_elems];
elem->window = win;
elem->type = type;
elem->func = NULL;
elem->format = NULL;
elem->font = &sys.font;
elem->text = &win->strings[GUI_STR_SIZE * win->n_elems];
elem->text[0] = 0;
elem->capacity = GUI_STR_SIZE;
elem->texture = 0;
elem->pos_x = x;
elem->pos_y = y;
elem->size_x = w;
elem->size_y = h;
elem->text_x = elem->text_y = elem->tsize_x = elem->tsize_y = 0;
elem->line_space = 0;
elem->font_size = 1;
elem->value = elem->def = elem->min = elem->max = 0;
elem->sel_start = elem->sel_end = elem->sel_drag = -1;
elem->id = win->n_elems;
elem->visible = elem->enabled = elem->t_dirty = elem->r_dirty = 1;
elem->pad = elem->xbreak = elem->precision = 0;
gui_update_style(elem, 1);
if(type != GUI_SLIDER) {
elem->margin_x1 = elem->margin_x2 = (type == GUI_FIELD || type == GUI_DROPDOWN_HANDLE) ? elem->border : 0;
elem->margin_y1 = elem->margin_y2 = (type == GUI_FIELD || type == GUI_DROPDOWN_HANDLE) ? elem->border : 0;
}
win->n_elems += 1;
win->min_x = MIN_VALUE(win->min_x, x);
win->min_y = MIN_VALUE(win->min_y, y);
win->max_x = MAX_VALUE(win->max_x, x + w);
win->max_y = MAX_VALUE(win->max_y, y + h);
return elem;
}
void gui_update_dropdown(window_t *win) {
if(win->selected && win->selected->type == GUI_DROPDOWN_HANDLE && win->selected->visible)
win->selected->r_dirty = 1;
}
void gui_update_text(gui_t *elem) {
if(elem->type != GUI_DROPDOWN_HANDLE) {
txt_size(&elem->tsize_x, &elem->tsize_y, elem->pos_x + ((elem->type != GUI_SLIDER) ? elem->margin_x1 : 0), elem->pos_y + ((elem->type != GUI_SLIDER) ? elem->margin_y1 : 0), 0,
elem->font_size * elem->font->yglyph, elem->font_size * (elem->font->yglyph + elem->line_space),
elem->pos_x + ((elem->type != GUI_SLIDER) ? elem->margin_x1 : 0), elem->pos_y + ((elem->type != GUI_SLIDER) ? elem->margin_y1 : 0),
elem->xbreak ? (elem->pos_x + (elem->size_x - ((elem->type != GUI_SLIDER) ? (elem->margin_x1 + elem->margin_x2) : 0))) : 0x7fffffff, 0x7fffffff, elem->font, elem->text);
if(elem->type != GUI_FIELD) {
if((elem->type != GUI_LABEL) || !elem->min)
elem->text_x = (elem->size_x - elem->tsize_x) / 2;
if((elem->type != GUI_LABEL) || !elem->max)
elem->text_y = (elem->size_y - elem->tsize_y - (elem->font_size * elem->font->yglyph)) / 2;
}
// logd("DBG", "s = %d %d; o = %d %d", elem->tsize_x, elem->tsize_y, elem->text_x, elem->text_y);
gui_update_dropdown(elem->window);
}
elem->t_dirty = 1;
}
void gui_set_text(gui_t *elem, const char *str) {
snprintf(elem->text, elem->capacity, "%s", str);
gui_update_text(elem);
}
int gui_slider_value(gui_t *elem) {
int r = elem->min + (((float)(int)(elem->sel_start - (elem->sel_end / 2))) * ((float)(int)(elem->max - elem->min)) / ((float)(int)(elem->size_x + 1 - elem->sel_end)));
return CLAMP_VALUE(r, elem->min, elem->max);
}
int gui_slider_pixel(gui_t *elem) {
int r = ((int)(float)(((float)(int)(elem->value - elem->min)) * ((float)(int)(elem->size_x + 1 - elem->sel_end)) / ((float)(int)(elem->max - elem->min)))) + (elem->sel_end / 2);
return CLAMP_VALUE(r, elem->sel_end / 2, elem->size_x - (elem->sel_end / 2));
}
void gui_set_slider(gui_t *elem, int value) {
elem->value = CLAMP_VALUE(value, elem->min, elem->max);
elem->sel_start = gui_slider_pixel(elem);
if(elem->format) {
elem->format(elem, elem->value);
gui_update_text(elem);
}
}
void gui_reformat(window_t *win) {
gui_t *elem;
for(int z = 0; z < win->n_elems; z++) {
elem = &win->elems[z];
if(elem->type == GUI_SLIDER)
elem->sel_start = gui_slider_pixel(elem);
if(elem->format) {
elem->format(elem, elem->value);
gui_update_text(elem);
if(elem->visible ^ 1)
elem->t_dirty = 0;
}
}
}
void gui_restyle(window_t *win) {
gui_t *elem;
for(int z = 0; z < win->n_elems; z++) {
elem = &win->elems[z];
gui_update_style(elem, 0);
if(elem->type == GUI_SLIDER)
elem->sel_start = gui_slider_pixel(elem);
}
}
void gui_deselect(window_t *win) {
if(win->selected && win->selected->type == GUI_FIELD) {
win->selected->sel_start = win->selected->sel_end = win->selected->sel_drag = -1;
win->tmr_leftmb = 0ULL;
win->selected->t_dirty = 1;
}
win->selected = NULL;
}
void gui_select(window_t *win, gui_t *elem) {
if(elem && win->selected != elem && elem->type == GUI_FIELD) {
if(elem->func) {
elem->func(elem, 4);
}
}
win->selected = elem;
}
void gui_open(window_t *win, byte type) {
win->queue = type;
}
void gui_reopen(window_t *win) {
win->queue = win->open; // GUI_REFRESH
}
void gui_fmt_keep(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s", elem->format_text);
}
void gui_fmt_toggle(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %s", elem->format_text, value ? STR_ON : STR_OFF);
}
void gui_fmt_enum(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %s", elem->format_text, ((const char **)elem->aux_data)[value]);
}
void gui_fmt_enums(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s", ((const char **)elem->aux_data)[value]);
}
void gui_fmt_enump(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %s", elem->format_text, *(elem->format_data[value]));
}
void gui_fmt_enumps(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s", *(elem->format_data[value]));
}
void gui_fmt_slider(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %d", elem->format_text, value);
}
void gui_fmt_fslider(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %.1f", elem->format_text, ((float)value) / 1000.0f);
}
void gui_fmt_fslider2(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %.2f", elem->format_text, ((float)value) / 1000.0f);
}
void gui_fmt_fslider0(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %d", elem->format_text, value / 1000);
}
void gui_fmt_pslider(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %d %%", elem->format_text, (int)(((float)value) / 10.0f));
}
void gui_fmt_drop(gui_t *elem, int value) {
int pos = 0;
for(int z = 0; z < elem->max && pos < (elem->capacity - 1); z++) {
pos += snprintf(&elem->text[pos], elem->capacity - pos, z ? "\n%s" : "%s", ((const char **)elem->aux_data)[z]);
}
}
void gui_fmt_dropp(gui_t *elem, int value) {
int pos = 0;
for(int z = 0; z < elem->max && pos < (elem->capacity - 1); z++) {
pos += snprintf(&elem->text[pos], elem->capacity - pos, z ? "\n%s" : "%s", *(elem->format_data[z]));
}
}
void gui_fnc_debug(gui_t *elem, int value) {
// logd(LOG_SYS, "%d -> %d", elem->id, value);
}
void gui_fnc_sdebug(gui_t *elem, int value) {
// logd(LOG_SYS, "%d -> %d (%d)", elem->id, value, elem->sel_start);
}
void gui_fnc_cvar_bool(gui_t *elem, int value) {
cvar_sbool(elem->cv_data, (byte)value);
}
void gui_fnc_cvar_int(gui_t *elem, int value) {
cvar_sint(elem->cv_data, value);
// if(gui.open == GUI_STYLE)
// gui_reopen();
}
void gui_fnc_cvar_float(gui_t *elem, int value) {
cvar_sfloat(elem->cv_data, ((float)value) / 1000.0f);
}
void gui_fnc_cvar_color(gui_t *elem, int value) {
cvar_scolor(elem->cv_data, (uint)value);
}
void gui_fnc_cvar_text(gui_t *elem, int value) {
if(value == 3)
cvar_sdef(elem->cv_data);
else if((value != 0 && value != -4) || !cvar_sstr(elem->cv_data, elem->text)) {
if(value == -4) {
cvar_format(elem->cv_data, elem->text);
gui_update_text(elem);
}
return;
}
cvar_format(elem->cv_data, elem->text);
gui_update_text(elem);
if(value != -4)
gui_deselect(elem->window);
// if(elem->window->open == GUI_STYLE)
// gui_restyle(elem->window);
}
gui_t *gui_add_custom(window_t *win, int x, int y, int w, int h, gui_func *func) {
gui_t *elem = gui_add_elem(win, x, y, w, h, GUI_CUSTOM);
elem->func = func;
return elem;
}
gui_t *gui_add_label(window_t *win, int x, int y, int w, int h, const char *text) {
gui_t *elem = gui_add_elem(win, x, y, w, h, GUI_LABEL);
snprintf(elem->text, elem->capacity, "%s", text);
gui_update_text(elem);
return elem;
}
gui_t *gui_add_llabel(window_t *win, int x, int y, int w, int h, const char *text) {
gui_t *elem = gui_add_label(win, x, y, w, h, text);
elem->min = 1;
elem->text_x = 0;
return elem;
}
gui_t *gui_add_fill(window_t *win, int x, int y, int w, int h, const char *text) {
return gui_set_style(gui_add_label(win, x, y, w, h, text), GUI_BUTTON, 3);
}
void gui_fnc_nav(gui_t *elem, int value) {
gui_open(elem->window, (byte)elem->value);
}
gui_t *gui_add_button(window_t *win, int x, int y, int w, int h, const char *text, gui_func *func) {
gui_t *elem = gui_add_elem(win, x, y, w, h, GUI_BUTTON);
snprintf(elem->text, elem->capacity, "%s", text);
gui_update_text(elem);
elem->func = func;
return elem;
}
gui_t *gui_add_nbutton(window_t *win, int x, int y, int w, int h, const char *text, byte gui) {
gui_t *elem = gui_add_button(win, x, y, w, h, text, gui_fnc_nav);
elem->value = (int)gui;
return elem;
}
gui_t *gui_add_fbutton(window_t *win, int x, int y, int w, int h, const char *text, gui_func *func, gui_func *format) {
gui_t *elem = gui_add_elem(win, x, y, w, h, GUI_BUTTON);
elem->format_text = text;
elem->func = func;
elem->format = format;
return elem;
}
gui_t *gui_add_toggle(window_t *win, int x, int y, int w, int h, const char *text, gui_func *func, byte def, byte init) {
gui_t *elem = gui_add_elem(win, x, y, w, h, init ? GUI_TOGGLE_ON : GUI_TOGGLE_OFF);
elem->format_text = text;
elem->func = func;
elem->format = gui_fmt_toggle;
elem->value = init;
elem->def = def;
return elem;
}
gui_t *gui_add_cvtoggle(window_t *win, int x, int y, int w, int h, const char *text, const char *name) {
cvar_t *cv = cvar_get(name);
gui_t *elem = gui_add_toggle(win, x, y, w, h, text, gui_fnc_cvar_bool, (byte)cv->def, (byte)cv->value);
elem->cv_data = cv;
return elem;
}
gui_t *gui_add_enum(window_t *win, int x, int y, int w, int h, const char *text, gui_func *func, const char **names, int states, int def, int init) {
gui_t *elem = gui_add_elem(win, x, y, w, h, GUI_ENUM);
elem->format_text = text;
elem->aux_data = names;
elem->func = func;
elem->format = gui_fmt_enum;
elem->value = init;
elem->max = states;
elem->def = def;
return elem;
}
gui_t *gui_add_cvbenum(window_t *win, int x, int y, int w, int h, const char *text, const char *name, const char ***names) {
cvar_t *cv = cvar_get(name);
gui_t *elem = gui_add_enum(win, x, y, w, h, text, gui_fnc_cvar_bool, NULL, cv->max, cv->def, cv->value);
elem->format_data = names;
elem->cv_data = cv;
elem->format = gui_fmt_enump;
return elem;
}
gui_t *gui_add_cvienum(window_t *win, int x, int y, int w, int h, const char *text, const char *name, const char ***names) {
cvar_t *cv = cvar_get(name);
gui_t *elem = gui_add_enum(win, x, y, w, h, text, gui_fnc_cvar_int, NULL, cv->max, cv->def, cv->value);
elem->format_data = names;
elem->cv_data = cv;
elem->format = gui_fmt_enump;
return elem;
}
gui_t *gui_add_slider(window_t *win, int x, int y, int w, int h, const char *text, gui_func *func, int min, int max, int def, int init) {
gui_t *elem = gui_add_elem(win, x, y, w, h, GUI_SLIDER);
elem->format_text = text;
elem->func = func;
elem->format = gui_fmt_slider;
elem->value = init;
elem->min = min;
elem->max = max;
elem->def = def;
return elem;
}
gui_t *gui_add_cvslider(window_t *win, int x, int y, int w, int h, const char *text, const char *name) {
cvar_t *cv = cvar_get(name);
gui_t *elem = gui_add_slider(win, x, y, w, h, text, gui_fnc_cvar_int, cv->min, cv->max, cv->def, cv->value);
elem->cv_data = cv;
return elem;
}
gui_t *gui_add_fslider(window_t *win, int x, int y, int w, int h, int prec, const char *text, gui_func *func, float min, float max, float def, float init) {
gui_t *elem = gui_add_elem(win, x, y, w, h, GUI_SLIDER);
elem->format_text = text;
elem->func = func;
elem->format = (prec == 1) ? gui_fmt_fslider : ((prec == 2) ? gui_fmt_fslider2 : ((prec == -1) ? gui_fmt_pslider : gui_fmt_fslider0));
elem->value = (int)(float)(init * 1000.0f);
elem->min = (int)(float)(min * 1000.0f);
elem->max = (int)(float)(max * 1000.0f);
elem->def = (int)(float)(def * 1000.0f);
elem->precision = (prec < 0) ? 0 : (byte)prec;
return elem;
}
gui_t *gui_add_cvfslider(window_t *win, int x, int y, int w, int h, int prec, const char *text, const char *name) {
cvar_t *cv = cvar_get(name);
gui_t *elem = gui_add_fslider(win, x, y, w, h, prec, text, gui_fnc_cvar_float, cvar_itf(cv->min), cvar_itf(cv->max), cvar_itf(cv->def), cvar_itf(cv->value));
elem->cv_data = cv;
return elem;
}
gui_t *gui_add_dropdown(window_t *win, int x, int y, int w, int h, const char *text, gui_func *func, const char **names, int states, int def, int init) {
gui_t *elem = gui_add_elem(win, x, y, w, h, GUI_DROPDOWN);
gui_t *drop = gui_add_elem(win, x, y + h, w, sys.font.yglyph * states + sys.style.border * 2, GUI_DROPDOWN_HANDLE);
elem->format_text = text;
elem->aux_data = drop->aux_data = names;
elem->func = func;
elem->format = gui_fmt_enum;
drop->format = gui_fmt_drop;
elem->value = init;
elem->max = drop->max = states;
elem->def = def;
drop->visible = 0;
drop->t_dirty = drop->r_dirty = 0;
return elem;
}
gui_t *gui_add_dropup(window_t *win, int x, int y, int w, int h, const char *text, gui_func *func, const char **names, int states, int def, int init) {
gui_t *elem = gui_add_elem(win, x, y, w, h, GUI_DROPDOWN);
gui_t *drop = gui_add_elem(win, x, y - (sys.font.yglyph * states + sys.style.border * 2), w,
sys.font.yglyph * states + sys.style.border * 2, GUI_DROPDOWN_HANDLE);
elem->format_text = text;
elem->aux_data = drop->aux_data = names;
elem->func = func;
elem->format = gui_fmt_enum;
drop->format = gui_fmt_drop;
elem->value = init;
elem->max = drop->max = states;
elem->def = def;
drop->visible = 0;
drop->t_dirty = drop->r_dirty = 0;
return elem;
}
gui_t *gui_add_cvbdrop(window_t *win, int x, int y, int w, int h, const char *text, const char *name, const char ***names) {
cvar_t *cv = cvar_get(name);
gui_t *elem = gui_add_dropdown(win, x, y, w, h, text, gui_fnc_cvar_bool, NULL, cv->max, cv->def, cv->value);
gui_t *drop = elem + 1;
elem->format_data = names;
drop->format_data = names;
elem->cv_data = cv;
drop->cv_data = cv;
elem->format = gui_fmt_enump;
drop->format = gui_fmt_dropp;
return elem;
}
gui_t *gui_add_cvidrop(window_t *win, int x, int y, int w, int h, const char *text, const char *name, const char ***names) {
cvar_t *cv = cvar_get(name);
gui_t *elem = gui_add_dropdown(win, x, y, w, h, text, gui_fnc_cvar_int, NULL, cv->max, cv->def, cv->value);
gui_t *drop = elem + 1;
elem->format_data = names;
drop->format_data = names;
elem->cv_data = cv;
drop->cv_data = cv;
elem->format = gui_fmt_enump;
drop->format = gui_fmt_dropp;
return elem;
}
gui_t *gui_add_field(window_t *win, int x, int y, int w, int h, char *buf, int capacity, gui_func *func, byte sidescroll, byte edit) {
gui_t *elem = gui_add_elem(win, x, y, w, h, GUI_FIELD);
// if(mono)
// elem->font = &sys.mono;
if(buf && capacity) {
elem->text = buf;
elem->capacity = capacity;
}
else if(buf) {
snprintf(elem->text, elem->capacity, "%s", buf);
}
gui_update_text(elem);
elem->func = func;
elem->value = edit;
elem->xbreak = !sidescroll;
if(sidescroll)
elem->text_y = (elem->size_y - (elem->margin_y1 + elem->margin_y2 + (elem->font->yglyph * elem->font_size))) / 2;
// logd("t", "%dbb", elem->text_y);
return elem;
}
gui_t *gui_add_cvfield(window_t *win, int x, int y, int w, int h, const char *name) {
cvar_t *cv = cvar_get(name);
gui_t *elem = gui_add_field(win, x, y, w, h, NULL, 0, gui_fnc_cvar_text, 1, 1);
elem->cv_data = cv;
cvar_format(cv, elem->text);
gui_update_text(elem);
return elem;
}
void gui_text_select(gui_t *elem, int x, int y, byte drag) {
int x1 = elem->pos_x + elem->margin_x1;
int y1 = elem->pos_y + elem->margin_y1;
int x2 = elem->size_x - (elem->margin_x1 + elem->margin_x2);
int y2 = elem->size_y - (elem->margin_y1 + elem->margin_y2);
int offset = txt_offset(&elem->min, &elem->max, x, y, x1 + (elem->xbreak ? 0 : elem->text_x), y1 + elem->text_y, elem->font_size * elem->font->yglyph,
x1 + elem->text_x, y1 + elem->text_y, elem->xbreak ? (elem->pos_x + x2) : 0x7fffffff, 0x7fffffff, elem->font, elem->text);
// logd("tst", "@A %d %d --> %d %d", x1, y1, x2, y2);
// logd("tst", "@C %d %d --> %d, %d %d", x, y, offset, elem->min, elem->max);
if(!drag) {
elem->sel_drag = elem->sel_start = elem->sel_end = offset;
}
else if(drag && elem->sel_drag >= 0 && offset >= elem->sel_drag) {
elem->sel_start = elem->sel_drag;
elem->sel_end = offset;
}
else if(drag && elem->sel_drag >= 0 && offset < elem->sel_drag) {
elem->sel_start = offset;
elem->sel_end = elem->sel_drag;
}
// logd("tst", "@S %d . %d . %d", elem->sel_start, elem->sel_drag, elem->sel_end);
elem->t_dirty = 1;
if(x < x1)
elem->window->scrollx = x1 - x;
else if(x >= (x1 + x2))
elem->window->scrollx = -(x - (x1 + x2));
if(y < y1)
elem->window->scrolly = y1 - y;
else if(y >= (y1 + y2))
elem->window->scrolly = -(y - (y1 + y2));
}
void gui_mouse(window_t *win, int btn, int x, int y, byte ctrl, byte shift) {
int prev;
gui_t *elem = gui_clicked(win, x, y);
if(win->selected != NULL && win->selected != elem && win->selected->type == GUI_FIELD) {
win->selected->sel_start = win->selected->sel_end = win->selected->sel_drag = -1;
win->tmr_leftmb = 0ULL;
win->selected->t_dirty = 1;
if(win->selected->func) {
win->selected->func(win->selected, -4);
}
if(elem && elem->type == GUI_FIELD && elem->func) {
elem->func(elem, 4);
}
}
else if(win->selected != NULL && win->selected != elem && win->selected->type == GUI_DROPDOWN_HANDLE) {
win->selected->visible = 0;
win->selected->r_dirty = 1;
return;
}
else if(elem && win->selected != elem && elem->type == GUI_FIELD) {
if(elem->func) {
elem->func(elem, 4);
}
}
win->selected = elem;
if(elem == NULL) {
return;
}
else if(elem->type == GUI_BUTTON) {
elem->func(elem, (ctrl || (btn == 3)) ? -1 : ((shift || (btn == 2)) ? 1 : 0));
if(elem->format) {
elem->format(elem, elem->value);
gui_update_text(elem);
}
}
else if((elem->type == GUI_TOGGLE_OFF) || (elem->type == GUI_TOGGLE_ON)) {
prev = elem->value;
if((elem->value = (ctrl || (btn == 3)) ? elem->def : (elem->value ^ 1)) != prev) {
elem->type = elem->value ? GUI_TOGGLE_ON : GUI_TOGGLE_OFF;
gui_update_style(elem, 1);
elem->func(elem, elem->value);
if(elem->format) {
elem->format(elem, elem->value);
gui_update_text(elem);
}
}
}
else if(elem->type == GUI_ENUM) {
prev = elem->value;
elem->value = (ctrl || (btn == 3)) ? elem->def : (elem->value + ((shift || (btn == 2)) ? -1 : 1));
elem->value = (elem->value == elem->max) ? 0 : ((elem->value == -1) ? (elem->max - 1) : elem->value);
if(elem->value != prev) {
elem->func(elem, elem->value);
if(elem->format) {
elem->format(elem, elem->value);
gui_update_text(elem);
}
}
}
else if(elem->type == GUI_SLIDER) {
prev = elem->value;
if(ctrl || (btn == 3)) {
elem->value = elem->def;
elem->sel_start = gui_slider_pixel(elem);
if(elem->value != prev) {
elem->func(elem, elem->value);
if(elem->format) {
elem->format(elem, elem->value);
gui_update_text(elem);
}
}
}
else {
elem->sel_start = x - elem->pos_x;
elem->value = gui_slider_value(elem);
elem->sel_start = gui_slider_pixel(elem);
if(elem->value != prev) {
elem->func(elem, elem->value);
if(elem->format) {
elem->format(elem, elem->value);
gui_update_text(elem);
}
}
}
}
else if(elem->type == GUI_DROPDOWN) {
prev = elem->value;
if(ctrl || (btn == 3)) {
if((elem->value = elem->def) != prev) {
elem->func(elem, elem->value);
if(elem->format) {
elem->format(elem, elem->value);
gui_update_text(elem);
}
}
}
else {
gui_t *drop = elem + 1;
drop->visible = 1;
drop->r_dirty = 1;
win->selected = drop;
}
}
else if(elem->type == GUI_DROPDOWN_HANDLE) {
gui_t *drop = elem - 1;
prev = drop->value;
drop->value = (y - (elem->pos_y + elem->margin_y1)) * drop->max / (elem->size_y - (elem->margin_y1 + elem->margin_y2));
drop->value = CLAMP_VALUE(drop->value, 0, drop->max - 1);
if(drop->value != prev) {
drop->func(drop, drop->value);
if(drop->format) {
drop->format(drop, drop->value);
gui_update_text(drop);
}
}
elem->visible = 0;
elem->r_dirty = 1;
}
else if(elem->type == GUI_FIELD) {
if(btn == 1) {
if((!shift) && ((sys.tmr_current - win->tmr_leftmb) <= (((ulong)sys.dclick_delay) * 1000ULL))) {
elem->sel_start = elem->sel_drag = 0;
elem->sel_end = strlen(elem->text);
elem->t_dirty = 1;
}
else {
gui_text_select(elem, x, y, shift);
}
win->tmr_leftmb = sys.tmr_current;
}
else if((btn == 3) && elem->func) {
elem->func(elem, 3);
}
}
}
void gui_mouserel(window_t *win) {
win->scrollx = win->scrolly = 0;
}
byte gui_drag(window_t *win, int x, int y) {
int prev;
gui_t *elem = win->selected;
if(elem == NULL) {
return 0;
}
else if(elem->type == GUI_SLIDER) {
x = (x < elem->pos_x) ? elem->pos_x : ((x >= (elem->pos_x + elem->size_x)) ? (elem->pos_x - 1 + elem->size_x) : x);
prev = elem->value;
elem->sel_start = x - elem->pos_x;
elem->value = gui_slider_value(elem);
elem->value = CLAMP_VALUE(elem->value, elem->min, elem->max);
elem->sel_start = gui_slider_pixel(elem);
if(elem->value != prev) {
elem->func(elem, elem->value);
if(elem->format) {
elem->format(elem, elem->value);
gui_update_text(elem);
}
}
}
else if(elem->type == GUI_FIELD) {
gui_text_select(elem, x, y, 1);
}
return elem->type != GUI_LABEL;
}
void gui_scroll(window_t *win, int scr_x, int scr_y, int x, int y, byte ctrl, byte shift) {
int prev;
gui_t *elem = gui_clicked(win, x, y);
if(elem == NULL) {
return;
}
else if((elem->type == GUI_SLIDER) && scr_y) {
prev = elem->value;
elem->value += (scr_y < 0 ? 1 : -1) * (ctrl ? (elem->precision ? 1 : 10) : ((elem->precision >= 2) ? 10 : (elem->precision ? 100 : 1))) * (shift ? (elem->precision ? 50 : 5) : 1);
elem->value = CLAMP_VALUE(elem->value, elem->min, elem->max);
elem->sel_start = gui_slider_pixel(elem);
if(elem->value != prev) {
elem->func(elem, elem->value);
if(elem->format) {
elem->format(elem, elem->value);
gui_update_text(elem);
}
}
}
else if(elem->type == GUI_FIELD) {
if(scr_y && elem->xbreak) {
int limit = (elem->font->yglyph * elem->font_size) + elem->tsize_y - (elem->size_y - (elem->margin_y1 + elem->margin_y2));
limit = CLAMP_VALUE(limit, 0, 0x7fffffff);
prev = elem->text_y;
elem->text_y += (scr_y < 0 ? -1 : 1) * (ctrl ? 1 : (elem->font->yglyph * elem->font_size)) * GUI_SCROLL_LN * (shift ? 10 : 1);
elem->text_y = CLAMP_VALUE(elem->text_y, -limit, 0);
if(elem->sel_start >= 0)
elem->max += (elem->text_y - prev);
elem->t_dirty = 1;
}
else if(scr_y || scr_x) {
int limit = (elem->font->xglyph * elem->font_size) + elem->tsize_x - (elem->size_x - (elem->margin_x1 + elem->margin_x2));
limit = CLAMP_VALUE(limit, 0, 0x7fffffff);
prev = elem->text_x;
elem->text_x += ((scr_y ? scr_y : (-scr_x)) < 0 ? -1 : 1) * (ctrl ? 1 : (elem->font->xglyph * elem->font_size)) * GUI_SCROLL_LN * (shift ? 10 : 1);
elem->text_x = CLAMP_VALUE(elem->text_x, -limit, 0);
if(elem->sel_start >= 0)
elem->min += (elem->text_x - prev);
elem->t_dirty = 1;
}
}
}
void gui_text_clamp_scroll(gui_t *elem) {
int limit;
if(elem->xbreak) {
limit = (elem->font->yglyph * elem->font_size) + elem->tsize_y - (elem->size_y - (elem->margin_y1 + elem->margin_y2));
limit = CLAMP_VALUE(limit, 0, 0x7fffffff);
elem->text_y = CLAMP_VALUE(elem->text_y, -limit, 0);
}
else {
limit = (elem->font->xglyph * elem->font_size) + elem->tsize_x - (elem->size_x - (elem->margin_x1 + elem->margin_x2));
limit = CLAMP_VALUE(limit, 0, 0x7fffffff);
elem->text_x = CLAMP_VALUE(elem->text_x, -limit, 0);
}
}
void gui_text_update_cur(gui_t *elem, int offset, byte shift) {
int x1 = elem->pos_x + elem->margin_x1;
int y1 = elem->pos_y + elem->margin_y1;
int x2 = elem->size_x - (elem->margin_x1 + elem->margin_x2);
int y2 = elem->size_y - (elem->margin_y1 + elem->margin_y2);
gui_text_clamp_scroll(elem);
txt_coord(&elem->min, &elem->max, offset, x1 + (elem->xbreak ? 0 : elem->text_x), y1 + elem->text_y, elem->font_size * elem->font->yglyph,
x1 + elem->text_x, y1 + elem->text_y, elem->xbreak ? (elem->pos_x + x2) : 0x7fffffff, 0x7fffffff, elem->font, elem->text);
if(shift) {
if(elem->xbreak && elem->max < y1)
elem->text_y += y1 - elem->max;
else if(elem->xbreak && (elem->max + (elem->font->yglyph * elem->font_size)) >= (y1 + y2))
elem->text_y -= (elem->max + (elem->font->yglyph * elem->font_size)) - (y1 + y2);
if(!(elem->xbreak) && elem->min < x1)
elem->text_x += x1 - elem->min;
else if(!(elem->xbreak) && (elem->min + (elem->font->xglyph * elem->font_size)) >= (x1 + x2))
elem->text_x -= (elem->min + (elem->font->xglyph * elem->font_size)) - (x1 + x2);
gui_text_update_cur(elem, offset, 0);
}
else {
elem->t_dirty = 1;
}
}
void gui_text_insert(gui_t *elem, const char *str) {
if(!str || (elem->sel_start == -1))
return;
int olen = strlen(elem->text);
int slen = elem->sel_end - elem->sel_start;
int plen;
str_strip(str, &sys.work_buf[1 + olen - elem->sel_end], WORK_BUF - (1 + olen - elem->sel_end), -1, elem->xbreak ? '\n' : ' ', ' ', 0);
plen = strlen(&sys.work_buf[1 + olen - elem->sel_end]);
// logd("t", "%d %d %d", olen, slen, plen);
if((plen + olen - slen) >= elem->capacity)
return;
memcpy(sys.work_buf, &elem->text[elem->sel_end], 1 + olen - elem->sel_end);
memcpy(&elem->text[elem->sel_start], &sys.work_buf[1 + olen - elem->sel_end], plen);
memcpy(&elem->text[elem->sel_start += plen], sys.work_buf, 1 + olen - elem->sel_end);
elem->sel_end = elem->sel_drag = elem->sel_start;
gui_update_text(elem);
gui_text_update_cur(elem, elem->sel_end, 1);
}
void gui_key(window_t *win, int key, byte ctrl, byte shift) {
gui_t *elem = win->selected;
if(elem == NULL) {
return;
}
else if(elem->type == GUI_FIELD) {
if(ctrl && key == KEYSYM_A) {
elem->sel_start = elem->sel_drag = 0;
elem->sel_end = strlen(elem->text);
elem->t_dirty = 1;
}
else if(ctrl && (key == KEYSYM_C) || (elem->value && (key == KEYSYM_X))) {
if(elem->sel_start >= 0 && elem->sel_start != elem->sel_end) { // fix empty
// char end = elem->text[elem->sel_end];
// elem->text[elem->sel_end] = 0;
str_strip(&elem->text[elem->sel_start], sys.work_buf, WORK_BUF, elem->sel_end - elem->sel_start, '\n', 0, '?');
wcf_setclip(sys.work_buf);
// elem->text[elem->sel_end] = end;
if(key == KEYSYM_X)
gui_text_insert(elem, "");
}
}
else if(elem->value && ctrl && key == KEYSYM_V) {
gui_text_insert(elem, wcf_getclip());
}
else if(elem->value && !ctrl && key == KEYSYM_RETURN) {
if(elem->xbreak) {
gui_text_insert(elem, "\n");
}
else if(elem->func) {
elem->func(elem, shift ? 2 : 0);
}
}
else if(elem->value && (!ctrl) && (key == KEYSYM_BACKSPACE || key == KEYSYM_DELETE)) {
if(elem->sel_start != elem->sel_end) {
gui_text_insert(elem, "");
}
else if(key == KEYSYM_DELETE && elem->sel_start >= 0) {
if(utf_readn(elem->text, &elem->sel_end)) {
gui_text_insert(elem, "");
}
else {
elem->sel_end = elem->sel_start;
}
}
else if(key == KEYSYM_BACKSPACE && elem->sel_start > 0) {
utf_rreadn(elem->text, &elem->sel_start);
gui_text_insert(elem, "");
}
}
else if(!ctrl && (key == KEYSYM_RIGHT || key == KEYSYM_LEFT)) {
if(key == KEYSYM_RIGHT && elem->sel_start != elem->sel_end) {
elem->sel_start = elem->sel_drag = elem->sel_end;
}
else if(key == KEYSYM_LEFT && elem->sel_start != elem->sel_end) {
elem->sel_end = elem->sel_drag = elem->sel_start;
}
if(key == KEYSYM_RIGHT && elem->sel_start >= 0) {
if(utf_readn(elem->text, &elem->sel_end)) {
elem->sel_start = elem->sel_drag = elem->sel_end;
}
else {
elem->sel_end = elem->sel_drag = elem->sel_start;
}
gui_text_update_cur(elem, elem->sel_end, 1);
}
else if(key == KEYSYM_LEFT && elem->sel_start >= 0) {
if(elem->sel_start > 0)
utf_rreadn(elem->text, &elem->sel_start);
elem->sel_end = elem->sel_drag = elem->sel_start;
gui_text_update_cur(elem, elem->sel_end, 1);
}
}
else if(!ctrl && (key == KEYSYM_DOWN || key == KEYSYM_UP)) {
if(elem->xbreak) {
if(key == KEYSYM_DOWN && elem->sel_start != elem->sel_end) {
elem->sel_start = elem->sel_drag = elem->sel_end;
}
else if(key == KEYSYM_UP && elem->sel_start != elem->sel_end) {
elem->sel_end = elem->sel_drag = elem->sel_start;
}
if(key == KEYSYM_DOWN && elem->sel_start >= 0) {
uint ch;
if(ch = utf_readn(elem->text, &elem->sel_end)) {
while(ch && ch != '\n') {
ch = utf_readn(elem->text, &elem->sel_end);
}
if(!ch)
elem->sel_end -= 1;
elem->sel_start = elem->sel_drag = elem->sel_end;
}
else {
elem->sel_end = elem->sel_drag = elem->sel_start;
}
gui_text_update_cur(elem, elem->sel_end, 1);
}
else if(key == KEYSYM_UP && elem->sel_start >= 0) {
uint ch;
if(elem->sel_start > 0) {
do {
ch = utf_rreadn(elem->text, &elem->sel_start);
}
while(ch && ch != '\n');
}
elem->sel_end = elem->sel_drag = elem->sel_start;
gui_text_update_cur(elem, elem->sel_end, 1);
}
}
else if(elem->func) {
elem->func(elem, (key == KEYSYM_DOWN) ? -1 : 1);
}
}
else if((!ctrl) && key == KEYSYM_TAB) {
if(elem->func) {
elem->func(elem, shift ? -6 : 6);
}
}
}
}
void gui_char(window_t *win, uint code) {
gui_t *elem = win->selected;
if(elem == NULL) {
return;
}
else if(elem->type == GUI_FIELD && elem->value) {
int pos = 0;
char chr[8];
utf_rwriten(chr, &pos, 8, code);
chr[pos] = 0;
gui_text_insert(elem, chr);
}
}
gui_t *gui_get(window_t *win, int id) {
return &win->elems[id];
}
void gui_fnc_quit(gui_t *elem, int value) {
sys.interrupted = 1;
}
byte gui_init_none(window_t *win, int frame_x, int frame_y, byte open) {
return 0;
}
void gui_fmt_degrees(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %.1f °", elem->format_text, ((float)value) / 1000.0f);
}
void gui_fmt_millis(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %d ms", elem->format_text, value);
}
void gui_fmt_seconds(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %d s", elem->format_text, value);
}
void gui_fmt_units(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %d U", elem->format_text, value);
}
void gui_fmt_funits(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %.1f U", elem->format_text, ((float)value) / 1000.0f);
}
void gui_fmt_chunks(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %d %s", elem->format_text, value, value == 1 ? STR_CHUNK : STR_CHUNKS);
}
void gui_fmt_uchunks(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %d %s [%d]", elem->format_text, value, value == 1 ? STR_CHUNK : STR_CHUNKS, value * CHUNK_SIZE);
}
void gui_fnc_con_line(gui_t *elem, int value) {
if(value == -4 || value == 3 || value == 2) {
return;
}
else if(value == -1 || value == 1) {
// ...
}
else if(value == -6 || value == 6) {
// ...
}
else if(value == 0) {
con_exec(elem->text);
elem->text[0] = 0;
// if(sys.con_autoclose)
// gui_open(elem->window, GUI_CONSOLE);
}
gui_update_text(elem);
elem->sel_start = elem->sel_end = elem->sel_drag = strlen(elem->text);
gui_text_update_cur(elem, elem->sel_start, 1);
// if(!value)
// gui_deselect();
}
void gui_fnc_con_clear(gui_t *elem, int value) {
elem = gui_get(elem->window, 5);
con_reset();
gui_update_text(elem);
elem->sel_start = elem->sel_end = elem->sel_drag = sys.log_len;
gui_text_update_cur(elem, elem->sel_start, 1);
}
static const char **gui_log_levels[] = {
&STR_LOG_LEVEL_SILENT,
&STR_LOG_LEVEL_USER,
&STR_LOG_LEVEL_ERROR,
&STR_LOG_LEVEL_WARN,
&STR_LOG_LEVEL_INFO,
&STR_LOG_LEVEL_PERF,
&STR_LOG_LEVEL_DEBUG,
&STR_LOG_LEVEL_TRACE
};
byte gl_isdebug();
const char *gl_getsuffix();
const char *framecode();
const char *tpscode();
ulong perf_get(byte section);
int gui_render_text(gui_t *elem, int x, int y, uint color, const char *text);
void gui_render_stats(gui_t *elem, int value) {
elem->t_dirty = 1;
if(!value)
return;
sprintf(&sys.work_buf[4096], sys.win_vsync ? COL_DGRAY"VSYNC" : (sys.sync_limited ? COL_GREEN"%d" : COL_RED"UNL"), sys.sync_limit);
sprintf(&sys.work_buf[5096], sys.ticked ? COL_GREEN"%.1f" : COL_DGRAY"PAUSE", (float)sys.tick_target / 1000.0f);
if(wcf.active)
sprintf(&sys.work_buf[6096], (sys.win_full == wcf.active) ? ", W %d x %d @ %d Hz" : ", W %d x %d", wcf.active->frame_x, wcf.active->frame_y, sys.win_refresh);
sprintf(sys.work_buf,
"%s%.2f"COL_RESET" %s [%s"COL_RESET"], %.3f ms%s\n"
"%s%.2f"COL_RESET" %s [%s"COL_RESET"], %.3f ms, E %d ms\n"
"S+%lld Speicherblöcke, %.2f MB, P %.2f MB\n"
"%d Shader; W+%d Bildpuffer (~%.2f MB, P ~%.2f MB)\n"
"1+%d Puffer (%.2f MB, P %.2f MB)\n"
"%d+%d Texturen (%.2f MB, P %.2f MB)\n"
"%d Drawlists, M %d (D %d, T %d)\n"
"%d/%d dyn. Lichter (D %.1f, V %.1f); %d Objekte (G %d), L %d, C %d"
,
framecode(), (sys.tmr_framerate < 1.0f) ? (1.0f / sys.tmr_framerate) : sys.tmr_framerate, sys.tmr_framerate < 1.0f ? "SPF" : "FPS", &sys.work_buf[4096],
((float)(sys.tmr_ttime - perf_get(PERF_WAIT))) / 1000.0f, wcf.active ? &sys.work_buf[6096] : "",
sys.ticked ? tpscode() : COL_DGRAY, sys.ticked ? ((sys.tick_tickrate < 1.0f) ? (1.0f / sys.tick_tickrate) : sys.tick_tickrate) : 0.0f,
(sys.ticked && sys.tick_tickrate < 1.0f) ? "SPT" : "TPS", &sys.work_buf[5096],
((float)sys.tick_time) / 1000.0f, sys.tick_timeout,
sys.mem_blocks, ((float)sys.mem_alloc) / 1024.0 / 1024.0, ((float)sys.mem_peak) / 1024.0 / 1024.0,
gdr.shd_loaded, gdr.fb_loaded, ((float)gdr.fb_mem) / 1024.0 / 1024.0, ((float)gdr.fb_peak) / 1024.0 / 1024.0,
gdr.buf_loaded, ((float)gdr.buf_mem) / 1024.0 / 1024.0, ((float)gdr.buf_peak) / 1024.0 / 1024.0,
sys.font_pages + 1, gdr.tex_loaded, ((float)gdr.tex_mem) / 1024.0 / 1024.0, ((float)gdr.tex_peak) / 1024.0 / 1024.0,
gdr.drawlists.stored, gdr.materials.stored, gdr.lists_drawn, gdr.tris_drawn,
(wcf.active && wcf.active->world) ? wcf.active->world->s_lights : 0, gdr.light_max, gdr.light_dist_cam, gdr.light_dist_vert,
(wcf.active && wcf.active->world) ? wcf.active->world->n_objects : 0,
(wcf.active && wcf.active->world) ? wcf.active->world->global_geom.stored : 0,
(wcf.active && wcf.active->world) ? wcf.active->world->n_lights : 0,
(wcf.active && wcf.active->world) ? wcf.active->world->n_chunks : 0
);
gui_render_text(elem, 0, 0, sys.style.text_label, sys.work_buf);
}
void gui_render_profiler(gui_t *elem, int value) {
elem->t_dirty = 1;
if(!value)
return;
int pos = 0;
for(int z = 0; z < PERF_SECTIONS; z++) {
pos += sprintf(&sys.work_buf[pos], "%s\n", perf_sections[z]);
}
gui_render_text(elem, 10, 0, sys.style.text_label, sys.work_buf);
pos = 0;
for(int z = 0; z < PERF_SECTIONS; z++) {
pos += sprintf(&sys.work_buf[pos], "%.3f ms\n", ((float)perf_get(z)) / 1000.0f);
}
gui_render_text(elem, 120, 0, sys.style.text_label, sys.work_buf);
pos = 0;
for(int z = 0; z < PERF_SECTIONS; z++) {
pos += sprintf(&sys.work_buf[pos], "%.2f %%\n", (((float)perf_get(z)) / ((float)sys.tmr_ttime)) * 100.0f);
}
gui_render_text(elem, 240, 0, sys.style.text_label, sys.work_buf);
}
void gui_fnc_optwin(gui_t *elem, int value);
void gui_fnc_plrwin(gui_t *elem, int value);
void gui_fnc_testwin(gui_t *elem, int value);
void gui_fnc_infowin(gui_t *elem, int value);
byte gui_init_console(window_t *win, int frame_x, int frame_y, byte open) {
gui_t *elem;
int y = 2 + 8;
gui_add_cvtoggle(win, 0, y * sys.font.yglyph, 160, 24, STR_CON_AUTOSCROLL, "con_autoscroll");
gui_add_cvtoggle(win, 160, y * sys.font.yglyph, 160, 24, STR_CON_TIMESTAMPS, "con_timestamps");
gui_add_cvbdrop(win, 320, y * sys.font.yglyph, 160, 24, STR_CON_LOGLEVEL, "con_loglevel", gui_log_levels);
gui_add_button(win, 480, y * sys.font.yglyph, 160, 24, STR_CON_CLEAR, gui_fnc_con_clear);
elem = gui_add_field(win, 0, y * sys.font.yglyph + 24, frame_x, frame_y - (y * sys.font.yglyph + 48 + 24), sys.con_buf, CON_BUF, NULL, 0, 0);
elem->color_fill_t &= 0x80ffffff;
elem->color_fill_b &= 0x80ffffff;
elem->color_brdr_t &= 0x80ffffff;
elem->color_brdr_b &= 0x80ffffff;
elem->precision = 0xff;
// gui_reformat();
elem->sel_start = elem->sel_end = elem->sel_drag = sys.log_len;
gui_update_text(elem);
gui_text_update_cur(elem, elem->sel_start, 1);
gui_select(win, gui_add_field(win, 0, frame_y - 48, frame_x, 24, sys.con_line, CON_LINE, gui_fnc_con_line, 1, 1));
y = 0;
sprintf(sys.work_buf, "OpenGL %s%s%s (GLSL %s)",
glGetString(GL_VERSION), gl_getsuffix(), gl_isdebug() ? " debug" : "", glGetString(GL_SHADING_LANGUAGE_VERSION));
gui_add_llabel(win, 0, (y++ * sys.font.yglyph), 640, sys.font.yglyph, sys.work_buf);
sprintf(sys.work_buf, "%s (%s)",
glGetString(GL_RENDERER), glGetString(GL_VENDOR));
gui_add_llabel(win, 0, (y++ * sys.font.yglyph), 640, sys.font.yglyph, sys.work_buf);
gui_add_custom(win, 0, (y * sys.font.yglyph), 640, 8 * sys.font.yglyph, gui_render_stats);
gui_add_custom(win, frame_x - (960 - 640), 0, 960 - 640, 10 * sys.font.yglyph, gui_render_profiler);
// if(frame_x > 640)
gui_add_fill(win, 640, ((2 + 8) * sys.font.yglyph), frame_x - 640, 24, "");
gui_add_button(win, 0, frame_y - 24, 160, 24, STR_TITLE_OPTIONS, gui_fnc_optwin);
gui_add_button(win, 160, frame_y - 24, 160, 24, STR_TITLE_PLAYER, gui_fnc_plrwin);
gui_add_button(win, 320, frame_y - 24, 160, 24, STR_TEST, gui_fnc_testwin);
gui_add_button(win, 480, frame_y - 24, 160, 24, STR_TITLE_INFO_SHORT, gui_fnc_infowin);
gui_add_fill(win, 640, frame_y - 24, frame_x - 640, 24, "");
return 0;
}
byte gui_init_main(window_t *win, int frame_x, int frame_y, byte open) {
// gui_size(520, 424);
gui_t *elem = gui_add_label(win, 20, 20, 480, 96, "");
elem->color_fill_t = elem->color_fill_b = 0xffffffff;
elem->border = 0;
elem->texture = gdr.tex_logo;
elem->precision = 0xff;
gui_add_label(win, 20, 120, 480, 48, SYS_PROGRAM);
// gui_add_nbutton(win, 80, 220, 360, 24, STR_TITLE_OPTIONS, GUI_CONTROL);
// gui_add_nbutton(win, 80, 260, 360, 24, STR_TITLE_PLAYER, GUI_PLAYER);
// gui_add_nbutton(win, 80, 300, 360, 24, STR_TITLE_INFO, GUI_INFO);
gui_add_button(win, 80, 380, 360, 24, STR_QUIT, gui_fnc_quit);
return 1;
}
byte gui_init_world(window_t *win, int frame_x, int frame_y, byte open) {
win->title = open ? STR_TITLE_MENU : STR_TITLE_NONE;
return 0;
}
static const char **gui_options_titles[] = {
&STR_TITLE_BINDS, &STR_TITLE_STYLE, &STR_TITLE_CONTROL, &STR_TITLE_DISPLAY, &STR_TITLE_GRAPHICS, &STR_TITLE_SOUND
};
byte gui_init_binds(window_t *win, int frame_x, int frame_y, byte open);
byte gui_init_style(window_t *win, int frame_x, int frame_y, byte open);
byte gui_init_control(window_t *win, int frame_x, int frame_y, byte open);
byte gui_init_display(window_t *win, int frame_x, int frame_y, byte open);
byte gui_init_graphics(window_t *win, int frame_x, int frame_y, byte open);
byte gui_init_sound(window_t *win, int frame_x, int frame_y, byte open);
static gui_initfnc *gui_options_init[] = {
gui_init_binds, gui_init_style, gui_init_control, gui_init_display, gui_init_graphics, gui_init_sound
};
byte gui_init_options(window_t *win, int frame_x, int frame_y, byte open) {
// gui_size(740, 444);
// gui_add_label(20, 20, 700, 24, 1, STR_TITLE_OPTIONS);
int x = 0;
int y = 0;
gui_t *elem;
win->title = *(gui_options_titles[open - 1]);
gui_options_init[open - 1](win, frame_x, frame_y, open);
for(int z = 0; z < 6; z++) {
elem = gui_add_nbutton(win, 240 * x, 24 * y, 240, 24, *(gui_options_titles[z]), z + 1);
if(open == z + 1)
gui_set_style(elem, GUI_TOGGLE_ON, 1);
if(++x == 5) {
x = 0;
++y;
}
}
// gui_add_nbutton(240 * 0, 0, 240, 24, 1, STR_TITLE_BINDS, GUI_BINDS);
// gui_add_nbutton(240 * 1, 0, 240, 24, 1, STR_TITLE_STYLE, GUI_STYLE);
// gui_add_nbutton(240 * 2, 0, 240, 24, 1, STR_TITLE_CONTROL, GUI_CONTROL);
// gui_add_nbutton(240 * 3, 0, 240, 24, 1, STR_TITLE_DISPLAY, GUI_DISPLAY);
// gui_add_nbutton(240 * 4, 0, 240, 24, 1, STR_TITLE_GRAPHICS, GUI_GRAPHICS);
// gui_add_nbutton(240 * 0, 24, 240, 24, 1, STR_TITLE_SOUND, GUI_SOUND);
// gui_add_nbutton(win, 0, frame_y - 24, frame_x, 24, STR_BACK, GUI_MENU);
// gui_reformat();
return 0;
}
void gui_fnc_bind(gui_t *elem, int value) {
int bind = (elem->id - 1) / 2;
if(value == -1) {
cvar_skey(bind, cvar_defkey(bind));
gui_reformat(elem->window);
}
else if(value == 1) {
cvar_skey(bind, 0);
gui_reformat(elem->window);
}
else {
sys.input = 0;
sys.keywait = bind + 1;
sys.keywin = elem->window;
}
}
byte gui_bind_dupe(byte bind) {
int key = sys.binds[bind].key;
if(!key)
return 0;
for(int z = 0; z < KEY_BINDS; z++) {
if((z != bind) && sys.binds[z].key && (sys.binds[z].key == key))
return 1;
}
return 0;
}
void gui_fmt_bind(gui_t *elem, int value) {
int bind = (elem->id - 1) / 2;
char v[32];
if(sys.keywait && ((sys.keywait - 1) == bind))
snprintf(elem->text, elem->capacity, FMT_BLINK COL_BLUE"***");
// else if(sys.binds[bind].key >= 33 && sys.binds[bind].key <= 126)
// snprintf(elem->text, elem->capacity, gui_bind_dupe(bind) ? COL_RED"<%c>" : COL_YELLOW"<%c>", (char)sys.binds[bind].key);
else
snprintf(elem->text, elem->capacity, gui_bind_dupe(bind) ? COL_RED"%s" : COL_YELLOW"%s", cvar_getkey(sys.binds[bind].key, v));
}
void gui_setkey(int key, byte release) {
if(sys.keywait) {
if(release) {
if((key > 0) && key == sys.key_release) {
cvar_skey(sys.keywait - 1, key);
sys.keywait = 0;
sys.key_release = 0;
gui_reformat(sys.keywin);
sys.keywin = NULL;
}
}
else if(!(sys.key_release)) {
if(key > 0) {
sys.key_release = key;
}
else {
cvar_skey(sys.keywait - 1, key);
sys.keywait = 0;
gui_reformat(sys.keywin);
sys.keywin = NULL;
}
}
}
}
void gui_fnc_bind_reset(gui_t *elem, int value) {
for(int z = 0; z < KEY_BINDS; z++) {
cvar_skey(z, cvar_defkey(z));
}
gui_reformat(elem->window);
}
byte gui_init_binds(window_t *win, int frame_x, int frame_y, byte open) {
// gui_size(740, 544);
// gui_add_label(20, 20, 700, 24, 1, STR_TITLE_BINDS);
int y = 0;
int x = 0;
for(int z = 0; z < KEY_BINDS; z++) {
gui_add_label(win, 20 + x * 180, 120 + y * 50, 160, 20, cvar_getbind(z));
gui_add_fbutton(win, 20 + x * 180, 140 + y * 50, 160, 24, "", gui_fnc_bind, gui_fmt_bind);
if(++x == 4) {
x = 0;
y++;
}
}
// y += x ? 1 : 0;
gui_add_button(win, 20, 500, 340, 24, STR_RESET, gui_fnc_bind_reset);
// gui_add_nbutton(380, 500, 340, 24, 1, STR_BACK, GUI_OPTIONS);
// gui_reformat();
// gui_init_options(win, frame_x, frame_y, open);
return 0;
}
void gui_fnc_style_reset(gui_t *elem, int value) {
cvar_t *cv;
window_t *win;
for(int z = 0; z < sys.n_cvars; z++) {
cv = &sys.cvars[z];
if(cv->category == CVAR_STYLE)
cvar_sdef(cv);
}
for(win = wcf.window_list; win; win = win->next) {
gui_reopen(win);
}
}
void gui_fnc_style_redraw(gui_t *elem, int value) {
window_t *win;
for(win = wcf.window_list; win; win = win->next) {
gui_reopen(win);
}
}
static const char *gui_drop_test[] = {"VALUE 1", "VALUE 2", "VALUE 3", "VALUE 4"};
static const char *gui_style_cvars[] = {
"color_select",
"color_hover_t",
"color_press_t",
"color_background_t",
"color_border_top",
"color_wborder_top",
"color_cursor",
"color_hover_b",
"color_press_b",
"color_background_b",
"color_border_btm",
"color_wborder_btm",
"color_button_top",
"color_textbox_top",
"color_window_top",
"color_label_text",
"color_button_text",
"border_gui",
"color_button_btm",
"color_textbox_btm",
"color_window_btm",
"color_textbox_text",
"color_window_text",
"width_handle"
};
static const char **gui_style_labels[] = {
&STR_GUI_SELCUR_COLOR,
&STR_GUI_HOVER_COLOR,
&STR_GUI_PRESS_COLOR,
&STR_GUI_BACK_COLOR,
&STR_GUI_BORDER_COLOR,
&STR_GUI_WBORDER_COLOR,
NULL, NULL, NULL, NULL, NULL, NULL,
&STR_GUI_DESC_BUTTON,
&STR_GUI_DESC_FIELD,
&STR_GUI_DESC_WINDOW,
&STR_GUI_DESC_LABEL,
&STR_GUI_DESC_BUTTON,
&STR_GUI_BORDER_WIDTH,
NULL, NULL, NULL,
&STR_GUI_DESC_FIELD,
&STR_GUI_DESC_WINDOW,
&STR_GUI_SLIDER_WIDTH
};
static const byte gui_style_y[] = {
1, 2, 4, 5
};
void gui_fnc_style_preset(gui_t *elem, int value) {
memcpy(&sys.style, elem->aux_data, sizeof(style_t));
cvar_t *cv;
window_t *win;
for(int z = 0; z < 24; z++) {
cv = cvar_get(gui_style_cvars[z]);
if(cv->type == CVAR_INT)
cvar_sint(cv, *((int*)cv->data));
else if(cv->type == CVAR_COLOR || cv->type == CVAR_COLOR_ALPHA)
cvar_scolor(cv, *((uint*)cv->data));
}
for(win = wcf.window_list; win; win = win->next) {
gui_reopen(win);
}
}
void gui_fmt_pixels(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%d px", value);
}
byte gui_init_style(window_t *win, int frame_x, int frame_y, byte open) {
// gui_size(980, 694);
// gui_add_label(20, 20, 140 * 6 + 20 * 5, 24, 1, STR_TITLE_STYLE);
int z = 0;
int s;
ulong iter = 0;
cvar_t *cv;
style_t *theme;
gui_add_label(win, 20, 80 + 10, 140 * 6 + 20 * 5, 20, STR_GUI_GENERAL);
gui_add_label(win, 20, 80 + 3 * 40 + 10, 140 * 3 + 20 * 2, 20, STR_GUI_FILL_COLOR);
gui_add_label(win, 20 + 3 * 160, 80 + 3 * 40 + 10, 140 * 2 + 20 * 1, 20, STR_GUI_TEXT_COLOR);
gui_add_label(win, 20 + 5 * 160, 80 + 3 * 40 + 10, 140, 20, STR_GUI_OTHER);
for(z = 0; z < 24; z++) {
cv = cvar_get(gui_style_cvars[z]);
s = z < 21 ? 0 : 10;
if(cv->type == CVAR_INT)
gui_add_cvslider(win, 20 + (z % 6) * 160, 100 + s + gui_style_y[z / 6] * 40, 140, 24, cv->name, cv->name)->format = gui_fmt_pixels;
else if(cv->type == CVAR_COLOR || cv->type == CVAR_COLOR_ALPHA)
gui_add_cvfield(win, 20 + (z % 6) * 160, 100 + s + gui_style_y[z / 6] * 40, 140, 24, cv->name);
if(gui_style_labels[z])
gui_add_label(win, 20 + (z % 6) * 160, 80 + s + gui_style_y[z / 6] * 40, 140, 20, *(gui_style_labels[z]));
}
z = 0;
while(theme = tbl_iter(&sys.themes, &iter)) {
gui_add_button(win, 20 + (z % 3) * 320, 80 + (z / 3 + 8) * 40, 300, 24, theme->name, gui_fnc_style_preset)->aux_data = theme;
z++;
}
gui_add_dropdown(win, 20, 540, 300, 24, "DROPDOWN", gui_fnc_debug, gui_drop_test, 4, 1, 0);
gui_add_button(win, 340, 540, 300, 24, "BUTTON", gui_fnc_debug);
gui_add_toggle(win, 660, 540, 140, 24, "TOGGLE", gui_fnc_debug, 0, 1);
gui_add_toggle(win, 820, 540, 140, 24, "TOGGLE", gui_fnc_debug, 1, 0);
gui_add_enum(win, 20, 580, 300, 24, "ENUM", gui_fnc_debug, gui_drop_test, 4, 2, 0);
gui_add_slider(win, 340, 580, 300, 24, "SLIDER", gui_fnc_sdebug, -20, 827, 60, 120);
gui_add_field(win, 660, 580, 300, 24, "FIELD", 0, NULL, 1, 1);
gui_add_button(win, 20, 650, 300, 24, STR_APPLY, gui_fnc_style_redraw);
gui_add_button(win, 340, 650, 300, 24, STR_RESET, gui_fnc_style_reset);
// gui_add_nbutton(660, 650, 300, 24, 1, STR_BACK, GUI_OPTIONS);
// gui_reformat();
// gui_init_options(win, frame_x, frame_y, open);
return 0;
}
void gui_fmt_dclick(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: <= %d ms", elem->format_text, value);
}
byte gui_init_control(window_t *win, int frame_x, int frame_y, byte open) {
// gui_size(740, 544);
// gui_add_label(20, 20, 700, 24, 1, STR_TITLE_CONTROL);
gui_add_cvfslider(win, 20, 80, 340, 24, 2, STR_PHY_SENSITIVITY, "phy_sensitivity");
gui_add_cvfslider(win, 380, 80, 340, 24, 2, STR_PHY_SPEED, "phy_speed");
// gui_add_cvfslider(win, 20, 120, 340, 24, 2, STR_PHY_GRAVITY, "phy_gravity");
// gui_add_cvfslider(win, 380, 120, 340, 24, 2, STR_PHY_FRICTION, "phy_friction");
gui_add_cvslider(win, 20, 120, 340, 24, STR_GUI_DCLICK_DELAY, "gui_dclick_delay")->format = gui_fmt_dclick;
// gui_add_nbutton(200, 500, 340, 24, 1, STR_BACK, GUI_OPTIONS);
// gui_reformat();
// gui_init_options(win, frame_x, frame_y, open);
return 0;
}
void gui_fmt_sync(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s: %.0d%s", elem->format_text, (value > 0 && value < elem->max) ? (value + 9) : 0, (value > 0 && value < elem->max) ? " FPS" : (value ? STR_UNLIMITED : STR_WIN_VSYNC));
}
void gui_fnc_sync(gui_t *elem, int value) {
cvar_sint(elem->cv_data, (value > 0 && value < elem->max) ? (value + 9) : (value ? -1 : 0));
}
void gui_list_modes() {
int offset = 0;
int pos = 0;
sys.n_modes = 0;
sys.vid_mode = 0;
const vidmode_t *modes = wcf_getmodes(&sys.n_modes);
const vidmode_t *wmode;
vidmode_t *mode;
if(sys.n_modes > VID_MODES) {
offset = sys.n_modes - VID_MODES;
sys.n_modes = VID_MODES;
}
for(int z = 0; z < sys.n_modes; z++) {
mode = &sys.vid_modes[z];
wmode = &modes[z + offset];
mode->width = wmode->width;
mode->height = wmode->height;
mode->refresh = wmode->refresh;
if(sys.win_xfull == mode->width && sys.win_yfull == mode->height && sys.win_refresh == mode->refresh)
sys.vid_mode = z;
}
}
void gui_fmt_mode(gui_t *elem, int value) {
vidmode_t *mode = &sys.vid_modes[value];
snprintf(elem->text, elem->capacity, "%s: %dx%d @ %d Hz", elem->format_text, mode->width, mode->height, mode->refresh);
}
void gui_fmt_mdrop(gui_t *elem, int value) {
vidmode_t *mode;
int pos = 0;
for(int z = 0; z < elem->max && pos < (elem->capacity - 1); z++) {
mode = &sys.vid_modes[z];
pos += snprintf(&elem->text[pos], elem->capacity - pos, z ? "\n%dx%d @ %d Hz" : "%dx%d @ %d Hz", mode->width, mode->height, mode->refresh);
}
}
// void win_full(byte full);
void gui_fnc_mode(gui_t *elem, int value) {
vidmode_t *mode = &sys.vid_modes[value];
sys.win_xfull = mode->width;
sys.win_yfull = mode->height;
sys.win_refresh = mode->refresh;
// win_full(1);
}
// void gui_fnc_full(gui_t *elem, int value) {
// win_full((byte)value);
// }
static const char **gui_mipmap_types[] = {
&STR_GFX_MIPMAP_OFF,
&STR_GFX_MIPMAP_NEAREST,
&STR_GFX_MIPMAP_LINEAR
};
static const char **gui_con_positions[] = {
&STR_CON_POS_TOP,
&STR_CON_POS_BTM
};
byte gui_init_display(window_t *win, int frame_x, int frame_y, byte open) {
gui_t *elem;
cvar_t *cv;
// gui_size(740, 544);
// gui_add_label(20, 20, 700, 24, 1, STR_TITLE_DISPLAY);
// gui_add_toggle(win, 20, 80, 340, 24, STR_WIN_FULLSCREEN, gui_fnc_full, 0, sys.win_full);
gui_list_modes();
elem = gui_add_dropdown(win, 20, 80, 340, 24, STR_WIN_FULLRES, gui_fnc_mode, NULL, sys.n_modes, sys.n_modes - 1, sys.vid_mode);
elem->format = gui_fmt_mode;
elem = elem + 1;
elem->capacity = VID_MODES*VID_MODE_STR;
elem->text = sys.vid_mode_list;
elem->format = gui_fmt_mdrop;
cv = cvar_get("win_sync");
elem = gui_add_slider(win, 20, 120, 340, 24, STR_WIN_SYNC, gui_fnc_sync, 0, 360 - 8, 0, (cv->value < 0) ? (360 - 8) : (cv->value ? ((cv->value < 10) ? 1 : (cv->value - 9)) : 0));
elem->cv_data = cv;
elem->format = gui_fmt_sync;
gui_add_cvtoggle(win, 380, 120, 340, 24, STR_WIN_FLUSH, "gl_vsync_flush");
gui_add_cvtoggle(win, 20, 200, 340, 24, STR_CON_OVERLAY, "con_overlay");
gui_add_cvslider(win, 380, 200, 340, 24, STR_CON_OPACITY, "con_opacity");
gui_add_cvslider(win, 20, 240, 340, 24, STR_CON_HEIGHT, "con_size");
gui_add_cvslider(win, 380, 240, 340, 24, STR_CON_FADEOUT, "con_fadeout")->format = gui_fmt_millis;
gui_add_cvbenum(win, 20, 280, 340, 24, STR_CON_POS, "con_position", gui_con_positions);
// gui_add_cvtoggle(win, 380, 280, 340, 24, STR_CON_MONOFONT, "con_monospace");
// gui_add_nbutton(200, 500, 340, 24, 1, STR_BACK, GUI_OPTIONS);
// gui_reformat();
// gui_init_options(win, frame_x, frame_y, open);
return 0;
}
byte gui_init_graphics(window_t *win, int frame_x, int frame_y, byte open) {
// gui_size(740, 544);
// gui_add_label(20, 20, 700, 24, 1, STR_TITLE_GRAPHICS);
gui_add_cvfslider(win, 20, 80, 340, 24, 1, STR_GFX_FOV, "gl_fov")->format = gui_fmt_degrees;
gui_add_label(win, 20, 120, 160, 24, STR_GFX_AMBIENT);
gui_add_cvfield(win, 200, 120, 160, 24, "gl_light_color");
gui_add_cvfslider(win, 380, 120, 340, 24, 2, STR_GFX_AMBIENT_X, "gl_ambient_x");
gui_add_cvfslider(win, 20, 160, 340, 24, 2, STR_GFX_AMBIENT_Y, "gl_ambient_y");
gui_add_cvfslider(win, 380, 160, 340, 24, 2, STR_GFX_AMBIENT_Z, "gl_ambient_z");
gui_add_cvslider(win, 20, 200, 340, 24, STR_GFX_LIGHT_MAX, "gl_dynlight_max");
gui_add_cvslider(win, 380, 200, 340, 24, STR_GFX_LIGHT_CHUNK, "gl_dynlight_chunkrange")->format = gui_fmt_uchunks;
gui_add_cvfslider(win, 20, 240, 340, 24, 1, STR_GFX_LIGHT_VIEW, "gl_dynlight_viewdist");
gui_add_cvfslider(win, 380, 240, 340, 24, 1, STR_GFX_LIGHT_VERT, "gl_dynlight_maxdist");
gui_add_cvfslider(win, 20, 280, 340, 24, 2, STR_GFX_LIGHT_BLEND, "gl_light_blend")->format = gui_fmt_pslider;
gui_add_cvtoggle(win, 20, 320, 340, 24, STR_GFX_TEXFILTER, "gl_tex_filter");
gui_add_cvbenum(win, 380, 320, 340, 24, STR_GFX_MIPMAPS, "gl_tex_mipmaps", gui_mipmap_types);
gui_add_cvfslider(win, 20, 360, 340, 24, 1, STR_GFX_ANISOTROPIC, "gl_tex_anisotropic"); // ->enabled = gdr.aniso_avail;
gui_add_cvslider(win, 20, 400, 340, 24, STR_GFX_DRAWDIST_H, "chunk_view_horizontal")->format = gui_fmt_uchunks;
gui_add_cvslider(win, 380, 400, 340, 24, STR_GFX_DRAWDIST_V, "chunk_view_vertical")->format = gui_fmt_uchunks;
// gui_add_nbutton(200, 500, 340, 24, 1, STR_BACK, GUI_OPTIONS);
// gui_reformat();
// gui_init_options(win, frame_x, frame_y, open);
return 0;
}
void snd_restart();
void gui_fnc_reset_snd(gui_t *elem, int value) {
snd_restart();
}
static const char **gui_sample_types[] = {
&STR_SND_FMT_S16LE,
&STR_SND_FMT_S32LE
};
static const char **gui_device_types[] = {
&STR_SND_DEV_DEFAULT,
&STR_SND_DEV_NULL,
&STR_SND_DEV_JACK,
&STR_SND_DEV_PULSE,
&STR_SND_DEV_HARDWARE,
&STR_SND_DEV_SOFTWARE,
&STR_SND_DEV_NONE
};
static const char **gui_volumes[] = {
&STR_SND_VOL_MASTER,
&STR_SND_VOL_MUSIC,
&STR_SND_VOL_SFX,
&STR_SND_VOL_GUI
};
static const int snd_sample_rates[] = {22050, 44100, 48000, 96000, 192000};
static const char *snd_sample_srates[] = {"22050 Hz [LQ]", "44100 Hz [CD]", "48000 Hz [DAT]", "96000 Hz [HQ]", "192000 Hz [XQ]"};
void gui_fnc_snd_rate(gui_t *elem, int value) {
cvar_setint("snd_sample_rate", snd_sample_rates[value]);
}
void gui_fmt_velofunc(gui_t *elem, int value) {
snprintf(elem->text, elem->capacity, "%s %d: %s", elem->format_text, value, (value ? (value == -128 ? STR_MID_VELO_ONE : (value < 0 ? STR_MID_VELO_ATTN : STR_MID_VELO_LOG)) : STR_MID_VELO_LIN));
}
byte gui_init_sound(window_t *win, int frame_x, int frame_y, byte open) {
// gui_size(740, 604 + 40 * (SND_VOLUMES / 2));
// gui_add_label(20, 20, 700, 24, 1, STR_TITLE_SOUND);
int rate = cvar_int("snd_sample_rate");
byte rpos;
for(rpos = 4; rpos > 0; rpos--) {
if(rate >= snd_sample_rates[rpos])
break;
}
gui_add_cvbdrop(win, 20, 80, 340, 24, STR_SND_DEVTYPE, "snd_device_type", gui_device_types);
gui_add_label(win, 20, 120, 280, 24, STR_SND_DEVICE_ID);
gui_add_cvfield(win, 300, 120, 60, 24, "snd_device_index");
gui_add_label(win, 380, 120, 280, 24, STR_SND_DEVICE_SUB);
gui_add_cvfield(win, 660, 120, 60, 24, "snd_device_sub");
gui_add_dropdown(win, 20, 160, 340, 24, STR_SND_SAMPLERATE, gui_fnc_snd_rate, snd_sample_srates, 5, 2, rpos);
gui_add_cvbdrop(win, 380, 160, 340, 24, STR_SND_FORMAT, "snd_sample_format", gui_sample_types);
gui_add_cvslider(win, 20, 200, 340, 24, STR_SND_BUFSIZE, "snd_buffer_size");
gui_add_cvslider(win, 380, 200, 340, 24, STR_SND_FRAMESIZE, "snd_frame_size");
gui_add_button(win, 20, 260, 700, 24, STR_SND_RESTART, gui_fnc_reset_snd);
gui_add_label(win, 20, 320, 700, 24, STR_TITLE_MIDI);
gui_add_cvtoggle(win, 20, 360, 340, 24, STR_MID_USEUNKN, "mid_play_unknown");
gui_add_cvtoggle(win, 380, 360, 340, 24, STR_MID_KEEPNOTES, "mid_keep_notes");
gui_add_cvtoggle(win, 20, 400, 340, 24, STR_MID_DONTFADE, "mid_dont_fade");
gui_add_cvtoggle(win, 380, 400, 340, 24, STR_MID_DEBUGEVT, "mid_debug_events");
gui_add_cvslider(win, 20, 440, 340, 24, STR_MID_VELOFUNC, "mid_velocity_func")->format = gui_fmt_velofunc;
gui_add_cvslider(win, 380, 440, 340, 24, STR_MID_OPVOICES, "mid_opl_voices");
gui_add_label(win, 20, 500, 700, 24, STR_TITLE_VOLUME);
int x = 20;
int y = 540;
for(int z = 0; z < SND_VOLUMES; z++) {
gui_add_cvfslider(win, x, y, 340, 24, -1, *(gui_volumes[z]), snd_cvar_volume[z]);
x = (x == 20) ? 380 : 20;
if(x == 20)
y += 40;
}
// gui_add_nbutton(200, y + 20, 340, 24, 1, STR_BACK, GUI_OPTIONS);
// gui_reformat();
// gui_init_options(win, frame_x, frame_y, open);
return 0;
}
byte gui_init_info(window_t *win, int frame_x, int frame_y, byte open) {
gui_add_field(win, 0, 0, frame_x, frame_y, SYS_INFO, sizeof(SYS_INFO), NULL, 0, 0);
return 0;
}
void plr_mode(byte repeat);
void plr_pause();
void plr_stop();
void plr_resume();
void plr_jump(int pos);
void plr_next();
void plr_prev();
void plr_rand();
void gui_plr_update_text(window_t *win) {
gui_t *elem = gui_get(win, 17);
const char *name = "";
int pos = (snd.mid_queue && (snd.mid_playpos != INT_MIN)) ? ((snd.mid_playpos < -1) ? (-(snd.mid_playpos) - 3) : snd.mid_playpos) : -1;
if(pos >= 0) {
if(pos != (snd.mid_queued - 1))
snd.mid_queue[pos+1][-1] = 0;
if(name = strrchr(&(snd.mid_queue[pos])[6], '/'))
name += 1;
else
name = &(snd.mid_queue[pos])[6];
snprintf(elem->text, elem->capacity, "%s: %d/%d - %s", STR_PLR_INFO, pos + 1, snd.mid_queued, name);
if(pos != (snd.mid_queued - 1))
snd.mid_queue[pos+1][-1] = '\n';
}
else {
snprintf(elem->text, elem->capacity, "%s", STR_PLR_INFO);
}
gui_update_text(elem);
}
void gui_plr_update(window_t *win) {
gui_t *elem = gui_get(win, 2);
snprintf(elem->text, elem->capacity, snd.mid_queue && (snd.mid_playpos >= -1) ? COL_GREEN SYM_PLAY : SYM_PLAY);
gui_update_text(elem);
elem = gui_get(win, 3);
snprintf(elem->text, elem->capacity, !snd.mid_queue || (snd.mid_playpos == INT_MIN) ? COL_RED SYM_STOP : SYM_STOP);
gui_update_text(elem);
elem = gui_get(win, 4);
snprintf(elem->text, elem->capacity, snd.mid_queue && (snd.mid_playpos != INT_MIN) && (snd.mid_playpos < -1) ? COL_YELLOW SYM_PAUSE : SYM_PAUSE);
gui_update_text(elem);
gui_plr_update_text(win);
}
void gui_fnc_plr_start(gui_t *elem, int value) {
plr_resume();
gui_update_text(gui_get(elem->window, 1));
gui_plr_update(elem->window);
}
void gui_fnc_plr_stop(gui_t *elem, int value) {
plr_stop();
gui_update_text(gui_get(elem->window, 1));
gui_plr_update(elem->window);
}
void gui_fnc_plr_pause(gui_t *elem, int value) {
plr_pause();
gui_update_text(gui_get(elem->window, 1));
gui_plr_update(elem->window);
}
void gui_fnc_plr_mode(gui_t *elem, int value) {
plr_mode((byte)value);
}
void gui_fnc_plr_prev(gui_t *elem, int value) {
plr_prev();
gui_update_text(gui_get(elem->window, 1));
gui_plr_update(elem->window);
}
void gui_fnc_plr_next(gui_t *elem, int value) {
plr_next();
gui_update_text(gui_get(elem->window, 1));
gui_plr_update(elem->window);
}
void gui_fnc_plr_rand(gui_t *elem, int value) {
plr_rand();
gui_update_text(gui_get(elem->window, 1));
gui_plr_update(elem->window);
}
void gui_fnc_plr_clear(gui_t *elem, int value) {
plr_stop();
plr_end();
elem = gui_get(elem->window, 1);
elem->text = &elem->window->strings[GUI_STR_SIZE * elem->id];
elem->text[0] = 0;
elem->capacity = GUI_STR_SIZE;
gui_update_text(elem);
elem->sel_start = elem->sel_end = elem->sel_drag = 0;
gui_text_update_cur(elem, elem->sel_start, 1);
elem->sel_start = elem->sel_end = elem->sel_drag = -1;
gui_plr_update(elem->window);
}
void gui_fnc_plr_open(gui_t *elem, int value) {
}
static const char *gui_plr_modes[] = {
SYM_CONTINUOS,
SYM_REPEAT,
SYM_LOOPED,
SYM_SHUFFLE
};
void gui_fnc_plr_jump(gui_t *elem, int value) {
if(!value && str_parse_int(elem->text, &value, -10) && value && (value <= snd.mid_queued)) {
plr_jump(value - 1);
snprintf(elem->text, elem->capacity, SYM_JUMPTO "#");
gui_update_text(elem);
gui_deselect(elem->window);
gui_text_update_cur(elem, elem->sel_start, 1);
gui_update_text(gui_get(elem->window, 1));
gui_plr_update(elem->window);
}
else if(value == 4) {
elem->text[0] = 0;
gui_update_text(elem);
gui_text_update_cur(elem, elem->sel_start, 1);
}
else if(value == -4) {
snprintf(elem->text, elem->capacity, SYM_JUMPTO "#");
gui_update_text(elem);
gui_text_update_cur(elem, elem->sel_start, 1);
}
}
void gui_fnc_plr_load(gui_t *elem, int value) {
if(!value) {
int count;
const char **files = file_list(&count, elem->text, mid_extensions, 3);
if(files) {
count = count > 999 ? 999 : count;
plr_queue(snd_bankfiles[snd.mid_bank], NULL, files, count);
mem_free(files);
elem->text[0] = 0;
gui_update_text(elem);
gui_deselect(elem->window);
gui_text_update_cur(elem, elem->sel_start, 1);
elem = gui_get(elem->window, 1);
elem->text = snd.mid_list;
elem->capacity = strlen(snd.mid_list) + 1;
gui_update_text(elem);
elem->sel_start = elem->sel_end = elem->sel_drag = 0;
gui_text_update_cur(elem, elem->sel_start, 1);
elem->sel_start = elem->sel_end = elem->sel_drag = -1;
gui_plr_update(elem->window);
}
}
}
// void gui_fnc_plr_bank(gui_t *elem, int value) {
// snd.mid_bank = (byte)value;
// }
void gui_fmt_bankdrop(gui_t *elem, int value) {
int pos = 0;
for(int z = 0; z < elem->max && pos < (elem->capacity - 1); z++) {
pos += snprintf(&elem->text[pos], elem->capacity - pos, z ? "\n%s%s" : "%s%s", ((const char **)elem->aux_data)[z], z < BNK_IDX_MELO_ONLY ? "" : (z < BNK_IDX_DRUM_ONLY ? " [0-127]" : " [128-255]"));
}
}
static const uint plr_waveforms[] = {0xff00ff00, 0xffff0000, 0xff0000ff, 0xff00ffff, 0xffff00ff, 0xffffff00, 0xff80ff00, 0xff00ff80};
int gui_render_bar(gui_t *elem, int x, int y, int w, int h, uint top, uint bottom, uint bg, int v) {
// if(v > 0)
v = (v < 0) ? 0 : v;
gfx_draw_rect(elem->pos_x + x, elem->pos_y + y, w, h, 0, 0, 0xff000000 | top, 0xff000000 | bottom, 0, 0);
if(++v < h)
gfx_draw_rect(elem->pos_x + x, elem->pos_y + y, w, h - v, 0, 0, 0xff000000 | bg, 0xff000000 | bg, 0, 0);
return h;
}
int gui_render_grad(gui_t *elem, int x, int y, int w, int h, uint top, uint bottom) {
gfx_draw_rect(elem->pos_x + x, elem->pos_y + y, w, h, 0, 0, 0xff000000 | top, 0xff000000 | bottom, 0, 0);
return h;
}
int gui_render_rect(gui_t *elem, int x, int y, int w, int h, uint color) {
gfx_draw_rect(elem->pos_x + x, elem->pos_y + y, w, h, 0, 0, 0xff000000 | color, 0xff000000 | color, 0, 0);
return h;
}
int gui_render_text(gui_t *elem, int x, int y, uint color, const char *text) {
txt_draw(elem->pos_x + x, elem->pos_y + y, 0, sys.font.yglyph, sys.font.yglyph, elem->pos_x + x, elem->pos_y + y, elem->pos_x + elem->size_x, elem->pos_y + elem->size_y,
0xff000000 | color, 0x00000000, &sys.font, text);
return sys.font.yglyph;
}
void gui_render_player(gui_t *elem, int value) {
elem->t_dirty = 1;
if(!value)
// return;
// gfx_draw_rect(elem->pos_x, elem->pos_y, elem->size_x, elem->size_y, 0, 0, 0xff404040, 0xff404040, 0, 0);
gui_render_grad(elem, 0, 0, elem->size_x, elem->size_y, sys.style.field_btm, sys.style.field_top);
if(snd.mid_visual ^ 1)
return;
pthread_mutex_lock(&sgt.lock);
if(!sgt.chip || !sgt.bank) {
pthread_mutex_unlock(&sgt.lock);
return;
}
opl3_chip *chip = sgt.chip;
bank_handle *bank = sgt.bank;
int nch = chip->n_voices;
int bx = elem->size_x / 2 - (nch * 6 + 2) / 2;
int by = elem->size_y / 2 - (698 + 20 * 4) / 2;
int x = bx;
int y = by;
if(value) {
x = bx - 84;
sprintf(&sys.work_buf[str_time(sys.work_buf, sgt.mid_time)], "\n%c%c%c%c %c",
(sgt.mid.tpqn && (((sgt.mid_tick / sgt.mid.tpqn) & 3) == 0)) ? '*' : '.',
(sgt.mid.tpqn && (((sgt.mid_tick / sgt.mid.tpqn) & 3) == 1)) ? '*' : '.',
(sgt.mid.tpqn && (((sgt.mid_tick / sgt.mid.tpqn) & 3) == 2)) ? '*' : '.',
(sgt.mid.tpqn && (((sgt.mid_tick / sgt.mid.tpqn) & 3) == 3)) ? '*' : '.',
plr_wheel[(sgt.mid_tick >> 5) & 3]);
gui_render_text(elem, x, y + 20, 0xffffff, sys.work_buf);
sprintf(sys.work_buf, COL_NEON"%s"COL_RESET"\n%d", STR_OPL_TICK, sgt.mid_tick);
gui_render_text(elem, x, y + 60, 0xffffff, sys.work_buf);
sprintf(sys.work_buf, COL_NEON"%s"COL_RESET"\n%d / %d", STR_OPL_ACTIVE, bank->v_used, bank->v_avail);
gui_render_text(elem, x, y + 100, 0xffffff, sys.work_buf);
sprintf(sys.work_buf, COL_NEON"%s"COL_RESET"\n%d +%dQ", STR_OPL_TEMPO, sgt.mid.uspb ? (60000000 / sgt.mid.uspb) : 0, sgt.mid.tpqn);
gui_render_text(elem, x, y + 140, 0xffffff, sys.work_buf);
x = bx;
pthread_mutex_unlock(&sgt.lock);
y += 3;
gui_render_text(elem, x, y, 0xffffff, STR_OPL_CHANNEL);
gui_render_text(elem, x, y + 20 + 226, 0xffffff, STR_OPL_MODULATOR);
gui_render_text(elem, x, y + 40 + 226 + 232, 0xffffff, STR_OPL_CARRIER);
gui_render_text(elem, x, y + 60 + 226 + 232 * 2, 0xffffff, STR_OPL_POINTER);
y -= 3;
// x -= 86;
x += nch * 6 + 2 + 1;
y += 20;
gui_render_text(elem, x, y + 0, 0xffffff, STR_OPL_OUTPUT);
gui_render_text(elem, x, y + 70, 0xffffff, STR_OPL_MODE);
gui_render_text(elem, x, y + 84, 0xffffff, STR_OPL_FEEDBACK);
gui_render_text(elem, x, y + 98, 0xffffff, STR_OPL_FREQUENCY);
y += 226 + 20;
for(int o = 0; o < 2; o++) {
gui_render_text(elem, x, y + 6, 0xffffff, STR_OPL_FLAGS);
gui_render_text(elem, x, y + 24, 0xffffff, STR_OPL_MULTIPLIER);
gui_render_text(elem, x, y + 42, 0xffffff, STR_OPL_LEVEL);
gui_render_text(elem, x, y + 96, 0xffffff, STR_OPL_KEYSCALE);
gui_render_text(elem, x, y + 110, 0xffffff, STR_OPL_WAVEFORM);
gui_render_text(elem, x, y + 124, 0xffffff, STR_OPL_ATTACK);
gui_render_text(elem, x, y + 142, 0xffffff, STR_OPL_DECAY);
gui_render_text(elem, x, y + 160, 0xffffff, STR_OPL_SUSTAIN);
gui_render_text(elem, x, y + 178, 0xffffff, STR_OPL_RELEASE);
gui_render_text(elem, x, y + 196, 0xffffff, STR_OPL_ENVELOPE);
y += 232 + 20;
}
return;
}
y += 20;
y += gui_render_rect(elem, x, y, nch * 6 + 2, 226, 0x3f0000) + 20;
y += gui_render_rect(elem, x, y, nch * 6 + 2, 232, 0x003f00) + 20;
y += gui_render_rect(elem, x, y, nch * 6 + 2, 232, 0x00003f) + 20;
y += gui_render_rect(elem, x, y, nch * 6 + 2, 8, 0x2f2f2f);
for(int c = 0; c < nch; c++) {
opl3_channel *channel = &chip->channel[c];
x = bx + 2 + 6 * c;
y = by + 2;
short **out = channel->out;
short accm = *out[0] + *out[1] + *out[2] + *out[3];
int chnlvl = 0;
for(int n = 0; n < 2; n++) {
chnlvl += (short)((accm * channel->level[n]) >> 16);
}
chnlvl = chnlvl < 0 ? (-chnlvl) : chnlvl;
chnlvl = (chnlvl * 16) / 2048;
chnlvl = chnlvl > 64 ? 64 : chnlvl;
int freq = (int)((((float)channel->f_num * 49716.0f) / powf(2.0f, 20.0f - (float)channel->block)) / 6210.0f * 128.0f);
/*
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + 10, 4, 64, 0, 0, 0xff000000, 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + 10 + 64 - chnlvl, 4, chnlvl, 0, 0, 0xffff0000, 0xff00ff00, 0, 0);
*/
y += 20;
y += gui_render_bar(elem, x, y, 4, 64, 0xff0000, 0x00ff00, 0x000000, chnlvl) + 2;
// int vid = c + 1;
// byte active = (channel->slots[0]->eg_out <= 0x100) || (channel->slots[1]->eg_out <= 0x100);
y += gui_render_rect(elem, x, y, 4, 4, ((channel->slots[0]->eg_out <= 0x100) || (channel->slots[1]->eg_out <= 0x100)) ? 0x00ff00 : 0x000000) + 2;
y += gui_render_rect(elem, x - (c & 1), y, 5, 4, channel->chtype != ch_2op ? 0xff00ff : 0x000000) + 2;
y += gui_render_grad(elem, x, y, 4, 4, channel->con ? 0x00ff00 : 0x808080, 0x0000ff) + 2;
y += gui_render_bar(elem, x, y, 4, 8, 0x00ff00, 0xffff00, 0x000000, channel->fb) + 2;
y += gui_render_bar(elem, x, y, 4, 128, 0x707070, 0x505050, 0x000000, freq) + 2;
gui_render_rect(elem, x, y - 130 + (127 - freq), 4, 1, 0xff0000);
/*
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + 10 + 64 + 2, 4, 4, 0, 0, active ? 0xff00ff00 : 0xff000000, active ? 0xff00ff00 : 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c - (c & 1), elem->pos_y + 10 + 64 + 8, 5, 4, 0, 0, channel->chtype != ch_2op ? 0xffff00ff : 0xff000000,
channel->chtype != ch_2op ? 0xffff00ff : 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + 10 + 64 + 14, 4, 4, 0, 0, channel->con ? 0xff00ff00 : 0xff808080, 0xff0000ff, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + 10 + 64 + 20, 4, 4 * (7 - channel->fb), 0, 0, 0xff000000, 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + 10 + 64 + 20 + 4 * (7 - channel->fb), 4, 4 * channel->fb, 0, 0, 0xff00ff00, 0xffffff00, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + 10 + 64 + 50, 4, 128, 0, 0, 0xff000000, 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + 10 + 64 + 50 + 128 - freq, 4, 1, 0, 0, 0xffff0000, 0xffff0000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + 10 + 64 + 50 + 129 - freq, 4, freq - 1, 0, 0, 0xff707070, 0xff505050, 0, 0);
*/
for(int o = 0; o < 2; o++) {
opl3_slot *slot = channel->slots[o];
/*
byte trem = slot->trem != (byte*)&slot->chip->zeromod;
byte sustain = (slot->reg_sl > 15) ? 0 : (15 - slot->reg_sl);
*/
y += 2;
y += 20;
/*
gfx_draw_rect(elem->pos_x + 10 + 6 * c + 0, elem->pos_y + y, 2, 4, 0, 0, o ? 0xff000000 : 0xff00ff00, o ? 0xff000000 : 0xff00ff00, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c + 2, elem->pos_y + y, 2, 4, 0, 0, o ? 0xff0000ff : 0xff000000, o ? 0xff0000ff : 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 6), 4, 4, 0, 0, slot->key ? 0xff00ff00 : 0xff000000, slot->key ? 0xff00ff00 : 0xff000000, 0, 0);
*/
// gui_render_rect(elem, x, y, 2, 4, o ? 0x000000 : 0x00ff00);
// y += gui_render_rect(elem, x + 2, y, 2, 4, o ? 0x0000ff : 0x000000) + 2;
y += gui_render_rect(elem, x, y, 4, 4, slot->key ? 0x00ff00 : 0x000000) + 2;
/*
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 6), 4, 4, 0, 0, trem ? 0xff00ff00 : 0xff000000, trem ? 0xff00ff00 : 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 4), 4, 4, 0, 0, slot->reg_vib ? 0xffffff00 : 0xff000000, slot->reg_vib ? 0xffffff00 : 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 4), 4, 4, 0, 0, slot->reg_type ? 0xffff0000 : 0xff000000, slot->reg_type ? 0xffff0000 : 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 4), 4, 4, 0, 0, slot->reg_ksr ? 0xffbf00bf : 0xff000000, slot->reg_ksr ? 0xffbf00bf : 0xff000000, 0, 0);
*/
y += gui_render_rect(elem, x, y, 4, 4, (slot->trem != (byte*)&slot->chip->zeromod) ? 0x5fdf00 : 0x000000);
y += gui_render_rect(elem, x, y, 4, 4, slot->reg_vib ? 0xffff00 : 0x000000);
y += gui_render_rect(elem, x, y, 4, 4, slot->reg_type ? 0xff0000 : 0x000000);
y += gui_render_rect(elem, x, y, 4, 4, slot->reg_ksr ? 0x5f00bf : 0x000000) + 2;
/*
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 6), 4, 2 * (15 - slot->reg_mult), 0, 0, 0xff000000, 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 2 * (15 - slot->reg_mult)), 4, 2 * slot->reg_mult, 0, 0, 0xffff0000, 0xffffff00, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 2 + 2 * slot->reg_mult), 4, slot->reg_tl, 0, 0, 0xff000000, 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += slot->reg_tl), 4, 63 - slot->reg_tl, 0, 0, 0xffff0000, 0xff00ff00, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 2 + 63 - slot->reg_tl), 4, 2 * (3 - slot->reg_ksl), 0, 0, 0xff000000, 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 2 * (3 - slot->reg_ksl)), 4, 2 * slot->reg_ksl, 0, 0, 0xff00ff00, 0xffffff00, 0, 0);
*/
y += gui_render_bar(elem, x, y, 4, 16, 0xff0000, 0xffff00, 0x000000, slot->reg_mult) + 2;
y += gui_render_bar(elem, x, y, 4, 64, 0xff0000, 0x00ff00, 0x000000, 63 - slot->reg_tl) + 2;
y += gui_render_bar(elem, x, y, 4, 4, 0x7f00ff, 0x3f00ff, 0x000000, slot->reg_ksl) + 2;
y += gui_render_rect(elem, x, y, 4, 8, 0x000000) + 2;
gui_render_rect(elem, x, y - 10 + (7 - slot->reg_wf), 4, 1, plr_waveforms[slot->reg_wf]);
/*
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 2 + 2 * slot->reg_ksl), 4, 2 * 8, 0, 0, 0xff000000, 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 2 * slot->reg_wf), 4, 2, 0, 0, plr_waveforms[slot->reg_wf], plr_waveforms[slot->reg_wf], 0, 0);
*/
y += gui_render_bar(elem, x, y, 4, 16, slot->eg_gen == 0 ? 0xff0000 : 0xaf0000, slot->eg_gen == 0 ? 0x00ffff : 0x00afaf, 0x000000, slot->reg_ar) + 2;
y += gui_render_bar(elem, x, y, 4, 16, slot->eg_gen == 1 ? 0xff0000 : 0xaf0000, slot->eg_gen == 1 ? 0x00ffff : 0x00afaf, 0x000000, slot->reg_dr) + 2;
y += gui_render_bar(elem, x, y, 4, 16, slot->eg_gen == 2 ? 0xff0000 : 0xaf0000, slot->eg_gen == 2 ? 0x00ffff : 0x00afaf, 0x000000, (slot->reg_sl > 15) ? 0 : (15 - slot->reg_sl)) + 2;
y += gui_render_bar(elem, x, y, 4, 16, slot->eg_gen == 3 ? 0xff0000 : 0xaf0000, slot->eg_gen == 3 ? 0x00ffff : 0x00afaf, 0x000000, slot->reg_rr) + 2;
y += gui_render_bar(elem, x, y, 4, 32, 0xff0000, 0x0000ff, 0x000000, (0x1ff - slot->eg_rout) / 16) + 2;
/*
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 2 + 2 * (8 - slot->reg_wf)), 4, 15 - slot->reg_ar, 0, 0, 0xff000000, 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 15 - slot->reg_ar), 4, slot->reg_ar, 0, 0, slot->eg_gen == 0 ? 0xff00ff00 : 0xffff0000, 0xffffff00, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 2 + slot->reg_ar), 4, 15 - slot->reg_dr, 0, 0, 0xff000000, 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 15 - slot->reg_dr), 4, slot->reg_dr, 0, 0, slot->eg_gen == 1 ? 0xff00ff00 : 0xffff0000, 0xffffff00, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 2 + slot->reg_dr), 4, 15 - sustain, 0, 0, 0xff000000, 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 15 - sustain), 4, sustain, 0, 0, slot->eg_gen == 2 ? 0xff00ff00 : 0xffff0000, 0xffffff00, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 2 + sustain), 4, 15 - slot->reg_rr, 0, 0, 0xff000000, 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 15 - slot->reg_rr), 4, slot->reg_rr, 0, 0, slot->eg_gen == 3 ? 0xff00ff00 : 0xffff0000, 0xffffff00, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 2 + slot->reg_rr), 4, slot->eg_rout / 16, 0, 0, 0xff000000, 0xff000000, 0, 0);
gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += slot->eg_rout / 16), 4, (0x1ff - slot->eg_rout) / 16, 0, 0, 0xffff0000, 0xff0000ff, 0, 0);
y += (0x1ff - slot->eg_rout) / 16;
*/
}
y += 2;
y += 20;
gui_render_rect(elem, x, y, 4, 4, bank->voiceindex == c ? 0x00ffff : 0x000000);
// gfx_draw_rect(elem->pos_x + 10 + 6 * c, elem->pos_y + (y += 2), 4, 4, 0, 0, bank->voiceindex == c ? 0xff00ffff : 0xff000000, bank->voiceindex == c ? 0xff00ffff : 0xff000000, 0, 0);
}
pthread_mutex_unlock(&sgt.lock);
}
byte gui_init_player(window_t *win, int frame_x, int frame_y, byte open) {
gui_add_fill(win, 0, 0, 696, 24, STR_TITLE_PLR_FULL);
gui_add_field(win, 0, 24, 720, frame_y - 316, snd.mid_queue ? snd.mid_list : "", snd.mid_queue ? (strlen(snd.mid_list) + 1) : 0, NULL, 0, 0);
gui_add_button(win, 0, frame_y - 24, 24, 24, SYM_PLAY, gui_fnc_plr_start);
gui_add_button(win, 24, frame_y - 24, 24, 24, SYM_STOP, gui_fnc_plr_stop);
gui_add_button(win, 48, frame_y - 24, 24, 24, SYM_PAUSE, gui_fnc_plr_pause);
gui_add_enum(win, 72, frame_y - 24, 24, 24, STR_PLR_MODE, gui_fnc_plr_mode, gui_plr_modes, 4, 0, snd.mid_repeat)->format = gui_fmt_enums;
gui_add_button(win, 120, frame_y - 24, 24, 24, SYM_PREV, gui_fnc_plr_prev);
gui_add_button(win, 144, frame_y - 24, 24, 24, SYM_NEXT, gui_fnc_plr_next);
gui_add_button(win, 168, frame_y - 24, 24, 24, SYM_PRANDOM, gui_fnc_plr_rand);
gui_add_field(win, 192, frame_y - 24, 48, 24, SYM_JUMPTO "#", 0, gui_fnc_plr_jump, 1, 1);
gui_add_button(win, 264, frame_y - 24, 24, 24, SYM_DELETE, gui_fnc_plr_clear);
cvar_t *cv = cvar_get("mid_opl_bank");
gui_t *elem = gui_add_dropup(win, 288, frame_y - 24, 192, 24, STR_MID_BANK, gui_fnc_cvar_bool, snd_banknames, cv->max, cv->def, cv->value);
elem->cv_data = cv;
elem = elem + 1;
elem->capacity = GUI_AUX_STR;
elem->text = win->str_aux;
elem->format = gui_fmt_bankdrop;
elem->cv_data = cv;
gui_add_field(win, 480, frame_y - 24, 216, 24, "", 0, gui_fnc_plr_load, 1, 1);
gui_add_button(win, 696, frame_y - 24, 24, 24, SYM_FOLDER, gui_fnc_plr_open);
gui_add_field(win, 0, frame_y - 268, 720, 120, snd.mid_info, 6 * SND_INFO, NULL, 0, 0);
gui_add_field(win, 0, frame_y - 124, 720, 100, snd.mid_klogger, SND_KLOG * SND_KAR, NULL, 0, 0);
gui_add_fill(win, 0, frame_y - 292, 720, 24, STR_PLR_INFO);
gui_add_fill(win, 96, frame_y - 24, 24, 24, "");
gui_add_fill(win, 240, frame_y - 24, 24, 24, "");
gui_add_fill(win, 0, frame_y - 148, 720, 24, STR_PLR_KARAOKE);
gui_add_custom(win, 720, 0, frame_x - 720, frame_y, gui_render_player);
gui_add_cvtoggle(win, 696, 0, 24, 24, "V", "mid_visualizer")->format = gui_fmt_keep;
// gui_add_nbutton(win, 0, 0, 160, 24, STR_BACK, GUI_MENU);
gui_plr_update(win);
// gui_reformat();
return 0;
}
window_t *win_open(int sx, int sy, int wx, int wy, int mx, int my, byte fixed, const char *title, gui_initfnc *initializer, byte type);
byte win_isopen(gui_initfnc *initializer) {
window_t *win;
for(win = wcf.window_list; win; win = win->next) {
if(win->initializer == initializer)
return 1;
}
return 0;
}
void gui_fnc_optwin(gui_t *elem, int value) {
if(!win_isopen(gui_init_options))
win_open(-1, 0, 1280, 800, 1280, 800, 0, "", gui_init_options, 3);
}
void gui_fnc_plrwin(gui_t *elem, int value) {
if(!snd.player)
snd.player = win_open(-1, 0, 1280, 800, 1280, 800, 0, STR_TITLE_PLAYER, gui_init_player, 1);
}
void test(window_t *win);
void gui_fnc_testwin(gui_t *elem, int value) {
test(win_open(1, 0, 960, 600, 0, 0, 0, "", gui_init_world, 1));
}
void gui_fnc_infowin(gui_t *elem, int value) {
if(!win_isopen(gui_init_info))
win_open(1, 0, 700, 410, 0, 0, 1, STR_TITLE_INFO, gui_init_info, 1);
}
void gui_fnc_win_minimize(gui_t *elem, int value) {
wcf_minimize(elem->window);
}
void gui_fnc_win_float(gui_t *elem, int value) {
wcf_floating(elem->window, (byte)value);
}
void gui_fnc_win_close(gui_t *elem, int value) {
win_closed(elem->window);
}
void gui_shift(window_t *win, byte shift) {
int shift_x = win->offset_x + (shift ? ((win->frame_x - (win->max_x - win->min_x)) / 2 - win->min_x) : 0);
int shift_y = win->offset_y + (shift ? ((win->frame_y - (win->max_y - win->min_y)) / 2 - win->min_y) : 0);
gui_t *elem;
for(int z = 0; z < win->n_elems; z++) {
elem = &win->elems[z];
elem->pos_x += shift_x;
elem->pos_y += shift_y;
if(elem->type == GUI_FIELD) {
elem->min += shift_x;
elem->max += shift_y;
}
}
}
void gui_init(window_t *win) {
byte shift;
// sys.mouse_clickx = INT_MIN;
// sys.mouse_clicky = INT_MIN;
win->selected = NULL;
win->tmr_leftmb = 0ULL;
win->min_x = win->min_y = INT_MAX;
win->max_x = win->max_y = INT_MIN;
win->n_elems = 0;
shift = win->initializer(win, win->frame_x, win->frame_y, win->open);
gui_reformat(win);
if(win->fb_x && win->fb_y)
gui_shift(win, shift);
if(sys.win_full == win)
return;
gui_t *header;
gui_set_style(gui_add_button(win, win->fb_x - WIN_TITLEBAR * 3, 0, WIN_TITLEBAR, WIN_TITLEBAR, "_", gui_fnc_win_minimize), GUI_CUSTOM, 1);
header = gui_set_style(gui_add_toggle(win, win->fb_x - WIN_TITLEBAR * 2, 0, WIN_TITLEBAR, WIN_TITLEBAR, "#", gui_fnc_win_float, 0, win->floating), GUI_CUSTOM, 1);
header->format = gui_fmt_keep;
header->format(header, header->value);
gui_update_text(header);
gui_set_style(gui_add_button(win, win->fb_x - WIN_TITLEBAR * 1, 0, WIN_TITLEBAR, WIN_TITLEBAR, "X", gui_fnc_win_close), GUI_CUSTOM, 1);
header = gui_set_style(gui_add_label(win, 0, 0, win->fb_x - WIN_TITLEBAR * 3, WIN_TITLEBAR, ""), GUI_CUSTOM, 3);
snprintf(header->text, header->capacity, "%s - %s", SYS_PROGRAM, win->title);
gui_update_text(header);
wcf_title(win, header->text);
// layout
}
void win_menu(window_t *win, byte menu);
void gui_check(window_t *win) {
if(win->queue != GUI_INVALID) {
// if(win->queue != GUI_REFRESH)
win->open = win->queue;
win->queue = GUI_INVALID;
win_menu(win, win->open ? 1 : 0);
gui_init(win);
win->redraw = 1;
if(!win->open)
sys.mouse_bind = 0;
}
}
void gui_await(window_t *win) {
if(win->selected && ((win->scrollx && !(win->selected->xbreak)) || (win->scrolly && win->selected->xbreak))) {
int n;
if(!(win->selected->xbreak))
win->selected->text_x += (n = (int)((float)((float)win->tmr_scroll) / 1000000.0f * 4.0f * ((float)win->scrollx)));
else
win->selected->text_y += (n = (int)((float)((float)win->tmr_scroll) / 1000000.0f * 4.0f * ((float)win->scrolly)));
if(n) {
gui_text_clamp_scroll(win->selected);
win->selected->t_dirty = 1;
}
if((((ulong)n) * 1000000ULL) <= win->tmr_scroll)
win->tmr_scroll -= ((ulong)n) * 1000000ULL;
else
win->tmr_scroll = 0ULL;
win->tmr_scroll += sys.tmr_delta;
}
}