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; } }