diff --git a/bind/v4k.lua b/bind/v4k.lua index 3dc3a5f..c4e1466 100644 --- a/bind/v4k.lua +++ b/bind/v4k.lua @@ -2101,25 +2101,25 @@ typedef union json_t { char* s; double f; int64_t i; uintptr_t p; union json_t* void* dll(const char *filename, const char *symbol); vec3 editor_pick(float mouse_x, float mouse_y); char* editor_path(const char *path); - float* editor_getf(const char *key); - int* editor_geti(const char *key); - char** editor_gets(const char *key); - int editor_send(const char *cmd, const char *optional_value); + float* engine_getf(const char *key); + int* engine_geti(const char *key); + char** engine_gets(const char *key); + int engine_send(const char *cmd, const char *optional_value); char* dialog_load(); char* dialog_save(); int gizmo(vec3 *pos, vec3 *rot, vec3 *sca); bool gizmo_active(); bool gizmo_hover(); - void kit_locale( const char *langcode_iso639_1 ); - void kit_set( const char *variable, const char *value ); - void kit_reset(); - void kit_insert( const char *id, const char *translation ); bool kit_load( const char *filename ); bool kit_merge( const char *filename ); + void kit_insert( const char *id, const char *translation ); void kit_clear(); - char* kit_translate( const char *id ); - char* kit_translate2( const char *id, const char *langcode_iso639_1 ); + void kit_set( const char *variable, const char *value ); + void kit_reset(); void kit_dump_state( FILE *fp ); + char* kit_translate2( const char *id, const char *langcode_iso639_1 ); + void kit_locale( const char *langcode_iso639_1 ); + char* kit_translate( const char *id ); char** file_list( const char *pathmasks ); bool file_write( const char *file, const void *ptr, int len ); bool file_append( const char *file, const void *ptr, int len ); @@ -2353,7 +2353,9 @@ TOUCH_1, bool input_touch_active(); void input_mappings(const char *filename); char input_keychar(unsigned code); + int input_enum(const char *sym); int input_anykey(); + int input_eval(const char *expression); void input_send( int vk ); char* save_input(); bool load_input(char* replay); @@ -2386,6 +2388,11 @@ MOUSE, MOUSE_X = MOUSE, MOUSE_Y, MOUSE_W, TOUCH_X1, TOUCH_Y1, TOUCH_X2, TOUCH_Y2, WINDOW_RESIZE, WINDOW_RESIZEX = WINDOW_RESIZE, WINDOW_RESIZEY, WINDOW_ORIENTATION, WINDOW_BATTERY, GAMEPAD_GUID, GAMEPAD_NAME, +}; +enum INPUT_ALIASES { +KEY_SHIFT = KEY_LSHIFT, +KEY_ALT = KEY_LALT, +KEY_CTRL = KEY_LCTRL, }; void* xrealloc(void* p, size_t sz); size_t xsize(void* p); @@ -3226,6 +3233,7 @@ PANEL_OPEN = 1, int ui_window(const char *title, int *enabled); int ui_panel(const char *title, int flags); int ui_collapse(const char *label, const char *id); + int ui_collapseo(const char *label, const char *id); int ui_contextual(); int ui_section(const char *title); int ui_int(const char *label, int *value); diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index d81df12..fa69cd9 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -15716,17 +15716,17 @@ API void* dll(const char *filename, const char *symbol); // in-game editor // - rlyeh, public domain. // -// @todo: merge editor1.c and editor2.c internals into this api +// @todo: merge editor1.c and editor3.c internals into this api //API void editor(); //API bool editor_active(); API vec3 editor_pick(float mouse_x, float mouse_y); API char* editor_path(const char *path); -API float* editor_getf(const char *key); -API int* editor_geti(const char *key); -API char** editor_gets(const char *key); -API int editor_send(const char *cmd, const char *optional_value); +API float* engine_getf(const char *key); +API int* engine_geti(const char *key); +API char** engine_gets(const char *key); +API int engine_send(const char *cmd, const char *optional_value); // open file dialog @@ -15741,19 +15741,19 @@ API bool gizmo_hover(); // localization kit (I18N, L10N) -API void kit_locale( const char *langcode_iso639_1 ); // set context language: enUS, ptBR, esES, ... -API void kit_set( const char *variable, const char *value ); // set context variable -API void kit_reset(); // reset all variables in context - -API void kit_insert( const char *id, const char *translation ); // insert single translation API bool kit_load( const char *filename ); // load translations file (xlsx) API bool kit_merge( const char *filename ); // merge translations file into existing context +API void kit_insert( const char *id, const char *translation ); // insert single translation unit API void kit_clear(); // delete all translations -API char* kit_translate( const char *id ); // perform a translation, given current locale +API void kit_set( const char *variable, const char *value ); // set context variable +API void kit_reset(); // reset all variables in context +API void kit_dump_state( FILE *fp ); // debug + API char* kit_translate2( const char *id, const char *langcode_iso639_1 ); // perform a translation given explicit locale -API void kit_dump_state( FILE *fp ); +API void kit_locale( const char *langcode_iso639_1 ); // set current locale: enUS, ptBR, esES, ... +API char* kit_translate( const char *id ); // perform a translation, given current locale #line 0 #line 1 "engine/split/v4k_file.h" @@ -16345,7 +16345,9 @@ API bool input_touch_active(); API void input_mappings(const char *filename); // update gamepad mappings (usually "gamecontrollerdb.txt" file) API char input_keychar(unsigned code); // Converts keyboard code to its latin char (if any) +API int input_enum(const char *sym); API int input_anykey(); +API int input_eval(const char *expression); // "down(X)*input(CTRL)" // inject state API void input_send( int vk ); // @todo @@ -16396,6 +16398,12 @@ enum INPUT_ENUMS { // -- strings: x2 gamepad GAMEPAD_GUID, GAMEPAD_NAME, }; +// these aliases do check both left and right counterparts +enum INPUT_ALIASES { + KEY_SHIFT = KEY_LSHIFT, + KEY_ALT = KEY_LALT, + KEY_CTRL = KEY_LCTRL, +}; #line 0 #line 1 "engine/split/v4k_memory.h" @@ -18207,6 +18215,7 @@ API int ui_notify(const char *title, const char *body); API int ui_window(const char *title, int *enabled); API int ui_panel(const char *title, int flags); // may be embedded inside a window, or standalone API int ui_collapse(const char *label, const char *id); +API int ui_collapseo(const char *label, const char *id); API int ui_contextual(); API int ui_section(const char *title); API int ui_int(const char *label, int *value); @@ -331479,7 +331488,7 @@ API void ProgressiveMesh(int vert_n, int vert_stride, const float *v, int tri_n, /* Other definitions */ #define MAX_ID_LEN 11 /* Max length of an identifier */ -#define OPERATORS "+-*/%(),^" /* Valid operators */ +#define OPERATORS "+-*/%(),^&|!" /* Valid operators */ #define EVAL_PI 3.141592654 #define EVAL_E 2.718281828 @@ -331638,7 +331647,7 @@ start: else if(isalpha(ev->p[0])) { /* Identifier */ int i; - for(i = 0; isalnum(ev->p[0]) && i < MAX_ID_LEN - 1; i++, ev->p++) + for(i = 0; (isalnum(ev->p[0]) || ev->p[0] == '_') && i < MAX_ID_LEN - 1; i++, ev->p++) ev->token[next_tok].s_val[i] = ev->p[0]; if(isalpha(ev->p[0])) longjmp(ev->j, ERR_LONGID); @@ -331685,7 +331694,7 @@ static void expr(struct eval *ev) { static void add_expr(struct eval *ev) { int t; mul_expr(ev); - while((t =EVAL_TYPE(ev)) == '+' || t == '-') { + while((t =EVAL_TYPE(ev)) == '+' || t == '-' || t == '|') { double a,b; lex(ev); mul_expr(ev); @@ -331694,8 +331703,10 @@ static void add_expr(struct eval *ev) { if(t == '+') push(ev, a + b); - else + else if(t == '-') push(ev, a - b); + else + push(ev, a || b); } } @@ -331703,7 +331714,7 @@ static void add_expr(struct eval *ev) { static void mul_expr(struct eval *ev) { int t; pow_expr(ev); - while((t = EVAL_TYPE(ev)) == '*' || t == '/' || t == '%') { + while((t = EVAL_TYPE(ev)) == '*' || t == '/' || t == '%' || t == '&') { double a,b; lex(ev); pow_expr(ev); @@ -331714,8 +331725,10 @@ static void mul_expr(struct eval *ev) { push(ev, a * b); else if(t == '/') push(ev, a / b); - else + else if(t == '%') push(ev, fmod(a, b)); + else + push(ev, a && b); } } @@ -331737,7 +331750,7 @@ static void pow_expr(struct eval *ev) { // uni_expr ::= ['+'|'-'] bra_expr static void uni_expr(struct eval *ev) { int t = '+'; - if(EVAL_TYPE(ev) == '-' || EVAL_TYPE(ev) == '+') { + if(EVAL_TYPE(ev) == '-' || EVAL_TYPE(ev) == '+' || EVAL_TYPE(ev) == '!') { t = EVAL_TYPE(ev); lex(ev); } @@ -331748,6 +331761,10 @@ static void uni_expr(struct eval *ev) { double a = pop(ev); push(ev, -a); } + else if(t == '!') { + double a = pop(ev); + push(ev, !a); + } } // bra_expr ::= '(' add_expr ')' | id_expr @@ -331773,18 +331790,23 @@ static void id_expr(struct eval *ev) { strcpy(id, ev->token[ev->cur_tok].s_val); lex(ev); if(EVAL_TYPE(ev) != '(') { - /**/ if(!istrcmp(id, "true")) push(ev, 1.0); - else if(!istrcmp(id, "false")) push(ev, 0.0); - else if(!istrcmp(id, "on")) push(ev, 1.0); - else if(!istrcmp(id, "off")) push(ev, 0.0); +#ifdef EVAL_EXTEND_CONSTANTS + EVAL_EXTEND_CONSTANTS +#else + if(0) {} +#endif + else if(!strcmp(id, "true")) push(ev, 1.0); + else if(!strcmp(id, "false")) push(ev, 0.0); + else if(!strcmp(id, "on")) push(ev, 1.0); + else if(!strcmp(id, "off")) push(ev, 0.0); // pi - 3.141592654 - else if(!istrcmp(id, "pi")) + else if(!strcmp(id, "pi")) push(ev, EVAL_PI); // e - base of natural logarithms, 2.718281828 - else if(!istrcmp(id, "e")) + else if(!strcmp(id, "e")) push(ev, EVAL_E); // deg - deg2rad, allows to degree conversion `sin(90*deg) = 1` - else if(!istrcmp(id, "deg")) + else if(!strcmp(id, "deg")) push(ev, EVAL_DEG); else EVAL_ERROR(ERR_CONST); @@ -331802,8 +331824,13 @@ static void id_expr(struct eval *ev) { } lex(ev); +#ifdef EVAL_EXTEND_FUNCTIONS + EVAL_EXTEND_FUNCTIONS +#else + if(0) {} +#endif // abs(x) - absolute value of x - if(!istrcmp(id, "abs")) { + else if(!istrcmp(id, "abs")) { if(nargs != 1) EVAL_ERROR(ERR_ARGS); push(ev, fabs(pop(ev))); } @@ -337751,8 +337778,6 @@ char* vfs_load(const char *pathfile, int *size_out) { // @todo: fix leaks, vfs_u } //} - // PRINTF("VFS: %s\n", pathfile); - int size = 0; void *ptr = 0; @@ -340689,6 +340714,10 @@ void input_update() { any_key |= (bits[i] = glfwGetKeys(win)[ table[i] ]); #endif } + // special cases: plain shift/alt/ctrl enums will also check right counterparts + any_key |= (bits[KEY_ALT] |= glfwGetKey(win, table[KEY_RALT] ) == GLFW_PRESS); + any_key |= (bits[KEY_CTRL] |= glfwGetKey(win, table[KEY_RCTRL] ) == GLFW_PRESS); + any_key |= (bits[KEY_SHIFT] |= glfwGetKey(win, table[KEY_RSHIFT] ) == GLFW_PRESS); #if is(ems) { @@ -340897,6 +340926,35 @@ vec2 input_filter_deadzone_4way( vec2 v, float deadzone ) { return vec2(v0, v1); } +int input_enum(const char *vk) { + static map(char*,int) m = 0; + do_once { + map_init_str(m); + #define k(VK) map_insert(m, STRINGIZE(KEY_##VK), KEY_##VK); map_insert(m, STRINGIZE(VK), KEY_##VK); + k(ESC) + k(TICK) k(1) k(2) k(3) k(4) k(5) k(6) k(7) k(8) k(9) k(0) k(BS) + k(TAB) k(Q) k(W) k(E) k(R) k(T) k(Y) k(U) k(I) k(O) k(P) + k(CAPS) k(A) k(S) k(D) k(F) k(G) k(H) k(J) k(K) k(L) k(ENTER) + k(LSHIFT) k(Z) k(X) k(C) k(V) k(B) k(N) k(M) k(RSHIFT) k(UP) + k(LCTRL) k(LALT) k(SPACE) k(RALT) k(RCTRL) k(LEFT) k(DOWN) k(RIGHT) + + k(F1) k(F2) k(F3) k(F4) k(F5) k(F6) k(F7) k(F8) k(F9) k(F10) k(F11) k(F12) k(PRINT) k(PAUSE) + k(INS) k(HOME) k(PGUP) k(DEL) k(END) k(PGDN) + + k(ALT) k(CTRL) k(SHIFT) + #undef k + }; + int *found = map_find(m, (char*)vk); + return found ? *found : -1; +} + +int input_eval(const char *expression) { + if( expression && expression[0] ) { + return eval(expression) > 0; + } + return 0; +} + // converts keyboard code to its latin char (if any) char input_keychar(unsigned code) { #define k2(VK,GLFW) [KEY_##VK] = GLFW_KEY_##GLFW @@ -352933,10 +352991,10 @@ static void nk_config_custom_fonts() { // ...with icons embedded on it. static struct icon_font { - const char *file; nk_rune range[3]; + const char *file; int yspacing; nk_rune range[3]; } icons[] = { - {"MaterialIconsSharp-Regular.otf", {UI_ICON_MIN, UI_ICON_MED /*MAX*/, 0}}, // "MaterialIconsOutlined-Regular.otf" "MaterialIcons-Regular.ttf" - {"materialdesignicons-webfont.ttf", {0xF68C /*ICON_MIN_MDI*/, 0xF1C80/*ICON_MAX_MDI*/, 0}}, + {"MaterialIconsSharp-Regular.otf", UI_ICON_SPACING_Y, {UI_ICON_MIN, UI_ICON_MED /*MAX*/, 0}}, // "MaterialIconsOutlined-Regular.otf" "MaterialIcons-Regular.ttf" + {"materialdesignicons-webfont.ttf", 2, {0xF68C /*ICON_MIN_MDI*/, 0xF1CC7/*ICON_MAX_MDI*/, 0}}, }; for( int f = 0; f < countof(icons); ++f ) for( char *data = vfs_load(icons[f].file, &datalen); data; data = 0 ) { @@ -352945,7 +353003,7 @@ static void nk_config_custom_fonts() { cfg.merge_mode = 1; cfg.spacing.x += UI_ICON_SPACING_X; - cfg.spacing.y += UI_ICON_SPACING_Y; + cfg.spacing.y += icons[f].yspacing; // cfg.font->ascent += ICON_ASCENT; // cfg.font->height += ICON_HEIGHT; @@ -353036,6 +353094,9 @@ table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = hover_hue; // nk_rgba(255, 0, 0, 255); // table[NK_COLOR_SELECT] = nk_rgba(57, 67, 61, 255); // table[NK_COLOR_SELECT_ACTIVE] = main; +// table[NK_COLOR_SELECT] = nk_rgba(255,255,255,255); +table[NK_COLOR_SELECT_ACTIVE] = main_hue; + // @transparent #if !is(ems) if( glfwGetWindowAttrib(window_handle(), GLFW_TRANSPARENT_FRAMEBUFFER) == GLFW_TRUE ) { @@ -353048,6 +353109,21 @@ table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = hover_hue; // nk_rgba(255, 0, 0, 255); nk_style_default(ui_ctx); nk_style_from_table(ui_ctx, table); + + if(1) + { + struct nk_style_selectable *select; + select = &ui_ctx->style.selectable; +// nk_zero_struct(*select); +// select->hover.data.color = hover_hue; +// select->normal_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); + select->text_hover = nk_rgba(0,192,255,255); + select->text_hover_active = select->text_hover; + select->text_normal_active = select->text_hover; // nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]).data.color; + select->rounding = 2.0f; + } + + struct nk_style *s = &ui_ctx->style; s->window.spacing = nk_vec2(4,0); s->window.combo_border = 0.f; @@ -354243,14 +354319,20 @@ int ui_panel_end() { } static unsigned ui_collapse_state = 0; +static bool ui_collapse_next_open = 0; int ui_collapse(const char *label, const char *id) { // mask: 0(closed),1(open),2(created) + int open = label[0] == '!'; label += open; uint64_t hash = 14695981039346656037ULL, mult = 0x100000001b3ULL; for(int i = 0; id[i]; ++i) hash = (hash ^ id[i]) * mult; ui_hue = (hash & 0x3F) / (float)0x3F; ui_hue += !ui_hue; - ui_collapse_state = nk_tree_base_(ui_ctx, NK_TREE_NODE, 0, label, NK_MINIMIZED, id, strlen(id), 0); - return ui_collapse_state & 1; // |1 open, |2 clicked, |4 toggled + ui_collapse_state = nk_tree_base_(ui_ctx, NK_TREE_NODE, 0, label, ui_collapse_next_open ? NK_MAXIMIZED : NK_MINIMIZED, id, strlen(id), 0); + return ui_collapse_next_open = 0, ui_collapse_state & 1; // |1 open, |2 clicked, |4 toggled +} +int ui_collapseo(const char *label, const char *id) { // mask: 0(closed),1(open),2(created) + ui_collapse_next_open = true; + return ui_collapse(label, id); } int ui_collapse_clicked() { return ui_collapse_state >> 1; // |1 clicked, |2 toggled @@ -354261,9 +354343,13 @@ int ui_collapse_end() { int ui_contextual() { +#if 0 struct nk_rect bounds = nk_widget_bounds(ui_ctx); // = nk_window_get_bounds(ui_ctx); bounds.y -= 25; return ui_popups() ? 0 : nk_contextual_begin(ui_ctx, 0, nk_vec2(150, 300), bounds); +#else + return ui_popups() ? 0 : nk_contextual_begin(ui_ctx, 0, nk_vec2(300, 220), nk_window_get_bounds(ui_ctx)); +#endif } int ui_contextual_end(int close) { if(close) nk_contextual_close(ui_ctx); @@ -354408,15 +354494,8 @@ int ui_label(const char *text) { nk_layout_row_dynamic(ui_ctx, 0, 1); return ui_label_(text, align); } -int ui_label2(const char *label, const char *text_) { - nk_layout_row_dynamic(ui_ctx, 0, 2); - - int align1 = NK_TEXT_LEFT; - int align2 = NK_TEXT_LEFT; - if( label ) align1 = label[0] == '>' ? (label++, NK_TEXT_RIGHT) : label[0] == '=' ? (label++, NK_TEXT_CENTERED) : label[0] == '<' ? (label++, NK_TEXT_LEFT) : NK_TEXT_LEFT; - if( text_ ) align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT; - ui_label_(label, align1); +static int nk_label_(struct nk_context *ui_ctx, const char *text_, int align2 ) { const struct nk_input *input = &ui_ctx->input; struct nk_rect bounds = nk_widget_bounds(ui_ctx); int is_hovering = nk_input_is_mouse_hovering_rect(input, bounds) && !ui_has_active_popups; @@ -354434,6 +354513,19 @@ ui_label_icon_clicked_R.x = is_hovering ? ( (int)((input->mouse.pos.x - bounds.x return ui_label_icon_clicked_R.x; } + + +int ui_label2(const char *label, const char *text_) { + nk_layout_row_dynamic(ui_ctx, 0, 2); + + int align1 = NK_TEXT_LEFT; + int align2 = NK_TEXT_LEFT; + if( label ) align1 = label[0] == '>' ? (label++, NK_TEXT_RIGHT) : label[0] == '=' ? (label++, NK_TEXT_CENTERED) : label[0] == '<' ? (label++, NK_TEXT_LEFT) : NK_TEXT_LEFT; + if( text_ ) align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT; + ui_label_(label, align1); + + return nk_label_(ui_ctx, text_, align2); +} int ui_label2_bool(const char *text, bool value) { bool b = !!value; return ui_bool(text, &b), 0; @@ -354861,8 +354953,8 @@ int ui_mat44(const char *label, float M[16]) { } int ui_buffer(const char *label, char *buffer, int buflen) { - nk_layout_row_dynamic(ui_ctx, 0, 2); - ui_label_(label, NK_TEXT_LEFT); + nk_layout_row_dynamic(ui_ctx, 0, 1 + (label && label[0])); + if(label && label[0]) ui_label_(label, NK_TEXT_LEFT); int active = nk_edit_string_zero_terminated(ui_ctx, NK_EDIT_AUTO_SELECT|NK_EDIT_CLIPBOARD|NK_EDIT_FIELD/*NK_EDIT_BOX*/|NK_EDIT_SIG_ENTER, buffer, buflen, nk_filter_default); return !!(active & NK_EDIT_COMMITED) ? nk_edit_unfocus(ui_ctx), 1 : 0; @@ -356281,9 +356373,9 @@ int window_frame_begin() { ); int choice = ui_toolbar(text); - if( choice == 1 ) editor_send("key_fullscreen",0); - if( choice == 2 ) editor_send("key_screenshot",0); - if( choice == 3 ) editor_send("key_record",0); + if( choice == 1 ) engine_send("key_fullscreen",0); + if( choice == 2 ) engine_send("key_screenshot",0); + if( choice == 3 ) engine_send("key_record",0); } EDITOR_UI_COLLAPSE(ICON_MD_KEYBOARD " Keyboard", "Debug.Keyboard") { ui_keyboard(); @@ -356360,8 +356452,8 @@ int window_frame_begin() { EDITOR_UI_COLLAPSE(power_icon_label, "Debug.Power") { int choice = ui_toolbar( ICON_MD_POWER ";" ICON_MD_BOLT ); - if( choice == 1 ) editor_send("key_battery","0"); - if( choice == 2 ) editor_send("key_battery","1"); + if( choice == 1 ) engine_send("key_battery","0"); + if( choice == 2 ) engine_send("key_battery","1"); } EDITOR_UI_COLLAPSE(ICON_MD_WATER " Reflection", "Debug.Reflect") { @@ -356378,8 +356470,8 @@ int window_frame_begin() { (has_menu ? ui_window_end : ui_panel_end)(); } - API int editor_tick(); - editor_tick(); + API int engine_tick(); + engine_tick(); } #endif // ENABLE_RETAIL @@ -358657,6 +358749,7 @@ vec3 editor_pick(float mouse_x, float mouse_y) { #endif } +#if 0 int editor_ui_bits8(const char *label, uint8_t *enabled) { // @to deprecate int clicked = 0; uint8_t copy = *enabled; @@ -358690,37 +358783,37 @@ int editor_ui_bits8(const char *label, uint8_t *enabled) { // @to deprecate nk_layout_row_end(ui_ctx); return clicked | (copy ^ *enabled); } +#endif - -typedef union editor_var { +typedef union engine_var { int i; float f; char *s; -} editor_var; -static map(char*,editor_var) editor_vars; -float *editor_getf(const char *key) { - if(!editor_vars) map_init_str(editor_vars); - editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) ); +} engine_var; +static map(char*,engine_var) engine_vars; +float *engine_getf(const char *key) { + if(!engine_vars) map_init_str(engine_vars); + engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); return &found->f; } -int *editor_geti(const char *key) { - if(!editor_vars) map_init_str(editor_vars); - editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) ); +int *engine_geti(const char *key) { + if(!engine_vars) map_init_str(engine_vars); + engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); return &found->i; } -char **editor_gets(const char *key) { - if(!editor_vars) map_init_str(editor_vars); - editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) ); +char **engine_gets(const char *key) { + if(!engine_vars) map_init_str(engine_vars); + engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); if(!found->s) found->s = stringf("%s",""); return &found->s; } -int editor_send(const char *cmd, const char *optional_value) { - unsigned *gamepads = editor_geti("gamepads"); // 0 off, mask gamepad1(1), gamepad2(2), gamepad3(4), gamepad4(8)... - unsigned *renders = editor_geti("renders"); // 0 off, mask: 1=lit, 2=ddraw, 3=whiteboxes - float *speed = editor_getf("speed"); // <0 num of frames to advance, 0 paused, [0..1] slomo, 1 play regular speed, >1 fast-forward (x2/x4/x8) - unsigned *powersave = editor_geti("powersave"); +int engine_send(const char *cmd, const char *optional_value) { + unsigned *gamepads = engine_geti("gamepads"); // 0 off, mask gamepad1(1), gamepad2(2), gamepad3(4), gamepad4(8)... + unsigned *renders = engine_geti("renders"); // 0 off, mask: 1=lit, 2=ddraw, 3=whiteboxes + float *speed = engine_getf("speed"); // <0 num of frames to advance, 0 paused, [0..1] slomo, 1 play regular speed, >1 fast-forward (x2/x4/x8) + unsigned *powersave = engine_geti("powersave"); char *name; /**/ if( !strcmp(cmd, "key_quit" )) record_stop(), exit(0); @@ -358744,14 +358837,14 @@ int editor_send(const char *cmd, const char *optional_value) { return 0; } -int editor_tick() { - enum { editor_hz = 60 }; - enum { editor_hz_mid = 18 }; - enum { editor_hz_low = 5 }; - if( *editor_geti("powersave") ) { +int engine_tick() { + enum { engine_hz = 60 }; + enum { engine_hz_mid = 18 }; + enum { engine_hz_low = 5 }; + if( *engine_geti("powersave") ) { // adaptive framerate int app_on_background = !window_has_focus(); - int hz = app_on_background ? editor_hz_low : editor_hz_mid; + int hz = app_on_background ? engine_hz_low : engine_hz_mid; window_fps_lock( hz < 5 ? 5 : hz ); } else { // window_fps_lock( editor_hz ); diff --git a/engine/split/3rd_eval.h b/engine/split/3rd_eval.h index 4cc360f..514c405 100644 --- a/engine/split/3rd_eval.h +++ b/engine/split/3rd_eval.h @@ -35,7 +35,7 @@ /* Other definitions */ #define MAX_ID_LEN 11 /* Max length of an identifier */ -#define OPERATORS "+-*/%(),^" /* Valid operators */ +#define OPERATORS "+-*/%(),^&|!" /* Valid operators */ #define EVAL_PI 3.141592654 #define EVAL_E 2.718281828 @@ -194,7 +194,7 @@ start: else if(isalpha(ev->p[0])) { /* Identifier */ int i; - for(i = 0; isalnum(ev->p[0]) && i < MAX_ID_LEN - 1; i++, ev->p++) + for(i = 0; (isalnum(ev->p[0]) || ev->p[0] == '_') && i < MAX_ID_LEN - 1; i++, ev->p++) ev->token[next_tok].s_val[i] = ev->p[0]; if(isalpha(ev->p[0])) longjmp(ev->j, ERR_LONGID); @@ -241,7 +241,7 @@ static void expr(struct eval *ev) { static void add_expr(struct eval *ev) { int t; mul_expr(ev); - while((t =EVAL_TYPE(ev)) == '+' || t == '-') { + while((t =EVAL_TYPE(ev)) == '+' || t == '-' || t == '|') { double a,b; lex(ev); mul_expr(ev); @@ -250,8 +250,10 @@ static void add_expr(struct eval *ev) { if(t == '+') push(ev, a + b); - else + else if(t == '-') push(ev, a - b); + else + push(ev, a || b); } } @@ -259,7 +261,7 @@ static void add_expr(struct eval *ev) { static void mul_expr(struct eval *ev) { int t; pow_expr(ev); - while((t = EVAL_TYPE(ev)) == '*' || t == '/' || t == '%') { + while((t = EVAL_TYPE(ev)) == '*' || t == '/' || t == '%' || t == '&') { double a,b; lex(ev); pow_expr(ev); @@ -270,8 +272,10 @@ static void mul_expr(struct eval *ev) { push(ev, a * b); else if(t == '/') push(ev, a / b); - else + else if(t == '%') push(ev, fmod(a, b)); + else + push(ev, a && b); } } @@ -293,7 +297,7 @@ static void pow_expr(struct eval *ev) { // uni_expr ::= ['+'|'-'] bra_expr static void uni_expr(struct eval *ev) { int t = '+'; - if(EVAL_TYPE(ev) == '-' || EVAL_TYPE(ev) == '+') { + if(EVAL_TYPE(ev) == '-' || EVAL_TYPE(ev) == '+' || EVAL_TYPE(ev) == '!') { t = EVAL_TYPE(ev); lex(ev); } @@ -304,6 +308,10 @@ static void uni_expr(struct eval *ev) { double a = pop(ev); push(ev, -a); } + else if(t == '!') { + double a = pop(ev); + push(ev, !a); + } } // bra_expr ::= '(' add_expr ')' | id_expr @@ -329,18 +337,23 @@ static void id_expr(struct eval *ev) { strcpy(id, ev->token[ev->cur_tok].s_val); lex(ev); if(EVAL_TYPE(ev) != '(') { - /**/ if(!istrcmp(id, "true")) push(ev, 1.0); - else if(!istrcmp(id, "false")) push(ev, 0.0); - else if(!istrcmp(id, "on")) push(ev, 1.0); - else if(!istrcmp(id, "off")) push(ev, 0.0); +#ifdef EVAL_EXTEND_CONSTANTS + EVAL_EXTEND_CONSTANTS +#else + if(0) {} +#endif + else if(!strcmp(id, "true")) push(ev, 1.0); + else if(!strcmp(id, "false")) push(ev, 0.0); + else if(!strcmp(id, "on")) push(ev, 1.0); + else if(!strcmp(id, "off")) push(ev, 0.0); // pi - 3.141592654 - else if(!istrcmp(id, "pi")) + else if(!strcmp(id, "pi")) push(ev, EVAL_PI); // e - base of natural logarithms, 2.718281828 - else if(!istrcmp(id, "e")) + else if(!strcmp(id, "e")) push(ev, EVAL_E); // deg - deg2rad, allows to degree conversion `sin(90*deg) = 1` - else if(!istrcmp(id, "deg")) + else if(!strcmp(id, "deg")) push(ev, EVAL_DEG); else EVAL_ERROR(ERR_CONST); @@ -358,8 +371,13 @@ static void id_expr(struct eval *ev) { } lex(ev); +#ifdef EVAL_EXTEND_FUNCTIONS + EVAL_EXTEND_FUNCTIONS +#else + if(0) {} +#endif // abs(x) - absolute value of x - if(!istrcmp(id, "abs")) { + else if(!istrcmp(id, "abs")) { if(nargs != 1) EVAL_ERROR(ERR_ARGS); push(ev, fabs(pop(ev))); } diff --git a/engine/split/v4k_editor.c b/engine/split/v4k_editor.c index aaf3772..85b0262 100644 --- a/engine/split/v4k_editor.c +++ b/engine/split/v4k_editor.c @@ -86,6 +86,7 @@ vec3 editor_pick(float mouse_x, float mouse_y) { #endif } +#if 0 int editor_ui_bits8(const char *label, uint8_t *enabled) { // @to deprecate int clicked = 0; uint8_t copy = *enabled; @@ -119,37 +120,37 @@ int editor_ui_bits8(const char *label, uint8_t *enabled) { // @to deprecate nk_layout_row_end(ui_ctx); return clicked | (copy ^ *enabled); } +#endif - -typedef union editor_var { +typedef union engine_var { int i; float f; char *s; -} editor_var; -static map(char*,editor_var) editor_vars; -float *editor_getf(const char *key) { - if(!editor_vars) map_init_str(editor_vars); - editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) ); +} engine_var; +static map(char*,engine_var) engine_vars; +float *engine_getf(const char *key) { + if(!engine_vars) map_init_str(engine_vars); + engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); return &found->f; } -int *editor_geti(const char *key) { - if(!editor_vars) map_init_str(editor_vars); - editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) ); +int *engine_geti(const char *key) { + if(!engine_vars) map_init_str(engine_vars); + engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); return &found->i; } -char **editor_gets(const char *key) { - if(!editor_vars) map_init_str(editor_vars); - editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) ); +char **engine_gets(const char *key) { + if(!engine_vars) map_init_str(engine_vars); + engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); if(!found->s) found->s = stringf("%s",""); return &found->s; } -int editor_send(const char *cmd, const char *optional_value) { - unsigned *gamepads = editor_geti("gamepads"); // 0 off, mask gamepad1(1), gamepad2(2), gamepad3(4), gamepad4(8)... - unsigned *renders = editor_geti("renders"); // 0 off, mask: 1=lit, 2=ddraw, 3=whiteboxes - float *speed = editor_getf("speed"); // <0 num of frames to advance, 0 paused, [0..1] slomo, 1 play regular speed, >1 fast-forward (x2/x4/x8) - unsigned *powersave = editor_geti("powersave"); +int engine_send(const char *cmd, const char *optional_value) { + unsigned *gamepads = engine_geti("gamepads"); // 0 off, mask gamepad1(1), gamepad2(2), gamepad3(4), gamepad4(8)... + unsigned *renders = engine_geti("renders"); // 0 off, mask: 1=lit, 2=ddraw, 3=whiteboxes + float *speed = engine_getf("speed"); // <0 num of frames to advance, 0 paused, [0..1] slomo, 1 play regular speed, >1 fast-forward (x2/x4/x8) + unsigned *powersave = engine_geti("powersave"); char *name; /**/ if( !strcmp(cmd, "key_quit" )) record_stop(), exit(0); @@ -173,14 +174,14 @@ int editor_send(const char *cmd, const char *optional_value) { return 0; } -int editor_tick() { - enum { editor_hz = 60 }; - enum { editor_hz_mid = 18 }; - enum { editor_hz_low = 5 }; - if( *editor_geti("powersave") ) { +int engine_tick() { + enum { engine_hz = 60 }; + enum { engine_hz_mid = 18 }; + enum { engine_hz_low = 5 }; + if( *engine_geti("powersave") ) { // adaptive framerate int app_on_background = !window_has_focus(); - int hz = app_on_background ? editor_hz_low : editor_hz_mid; + int hz = app_on_background ? engine_hz_low : engine_hz_mid; window_fps_lock( hz < 5 ? 5 : hz ); } else { // window_fps_lock( editor_hz ); diff --git a/engine/split/v4k_editor.h b/engine/split/v4k_editor.h index 24d36c9..7abb8ec 100644 --- a/engine/split/v4k_editor.h +++ b/engine/split/v4k_editor.h @@ -2,17 +2,17 @@ // in-game editor // - rlyeh, public domain. // -// @todo: merge editor1.c and editor2.c internals into this api +// @todo: merge editor1.c and editor3.c internals into this api //API void editor(); //API bool editor_active(); API vec3 editor_pick(float mouse_x, float mouse_y); API char* editor_path(const char *path); -API float* editor_getf(const char *key); -API int* editor_geti(const char *key); -API char** editor_gets(const char *key); -API int editor_send(const char *cmd, const char *optional_value); +API float* engine_getf(const char *key); +API int* engine_geti(const char *key); +API char** engine_gets(const char *key); +API int engine_send(const char *cmd, const char *optional_value); // open file dialog @@ -27,16 +27,16 @@ API bool gizmo_hover(); // localization kit (I18N, L10N) -API void kit_locale( const char *langcode_iso639_1 ); // set context language: enUS, ptBR, esES, ... -API void kit_set( const char *variable, const char *value ); // set context variable -API void kit_reset(); // reset all variables in context - -API void kit_insert( const char *id, const char *translation ); // insert single translation API bool kit_load( const char *filename ); // load translations file (xlsx) API bool kit_merge( const char *filename ); // merge translations file into existing context +API void kit_insert( const char *id, const char *translation ); // insert single translation unit API void kit_clear(); // delete all translations -API char* kit_translate( const char *id ); // perform a translation, given current locale +API void kit_set( const char *variable, const char *value ); // set context variable +API void kit_reset(); // reset all variables in context +API void kit_dump_state( FILE *fp ); // debug + API char* kit_translate2( const char *id, const char *langcode_iso639_1 ); // perform a translation given explicit locale -API void kit_dump_state( FILE *fp ); +API void kit_locale( const char *langcode_iso639_1 ); // set current locale: enUS, ptBR, esES, ... +API char* kit_translate( const char *id ); // perform a translation, given current locale diff --git a/engine/split/v4k_file.c b/engine/split/v4k_file.c index d515ee6..2f86edb 100644 --- a/engine/split/v4k_file.c +++ b/engine/split/v4k_file.c @@ -820,8 +820,6 @@ char* vfs_load(const char *pathfile, int *size_out) { // @todo: fix leaks, vfs_u } //} - // PRINTF("VFS: %s\n", pathfile); - int size = 0; void *ptr = 0; diff --git a/engine/split/v4k_input.c b/engine/split/v4k_input.c index 6ae7c66..1610c9d 100644 --- a/engine/split/v4k_input.c +++ b/engine/split/v4k_input.c @@ -254,6 +254,10 @@ void input_update() { any_key |= (bits[i] = glfwGetKeys(win)[ table[i] ]); #endif } + // special cases: plain shift/alt/ctrl enums will also check right counterparts + any_key |= (bits[KEY_ALT] |= glfwGetKey(win, table[KEY_RALT] ) == GLFW_PRESS); + any_key |= (bits[KEY_CTRL] |= glfwGetKey(win, table[KEY_RCTRL] ) == GLFW_PRESS); + any_key |= (bits[KEY_SHIFT] |= glfwGetKey(win, table[KEY_RSHIFT] ) == GLFW_PRESS); #if is(ems) { @@ -462,6 +466,35 @@ vec2 input_filter_deadzone_4way( vec2 v, float deadzone ) { return vec2(v0, v1); } +int input_enum(const char *vk) { + static map(char*,int) m = 0; + do_once { + map_init_str(m); + #define k(VK) map_insert(m, STRINGIZE(KEY_##VK), KEY_##VK); map_insert(m, STRINGIZE(VK), KEY_##VK); + k(ESC) + k(TICK) k(1) k(2) k(3) k(4) k(5) k(6) k(7) k(8) k(9) k(0) k(BS) + k(TAB) k(Q) k(W) k(E) k(R) k(T) k(Y) k(U) k(I) k(O) k(P) + k(CAPS) k(A) k(S) k(D) k(F) k(G) k(H) k(J) k(K) k(L) k(ENTER) + k(LSHIFT) k(Z) k(X) k(C) k(V) k(B) k(N) k(M) k(RSHIFT) k(UP) + k(LCTRL) k(LALT) k(SPACE) k(RALT) k(RCTRL) k(LEFT) k(DOWN) k(RIGHT) + + k(F1) k(F2) k(F3) k(F4) k(F5) k(F6) k(F7) k(F8) k(F9) k(F10) k(F11) k(F12) k(PRINT) k(PAUSE) + k(INS) k(HOME) k(PGUP) k(DEL) k(END) k(PGDN) + + k(ALT) k(CTRL) k(SHIFT) + #undef k + }; + int *found = map_find(m, (char*)vk); + return found ? *found : -1; +} + +int input_eval(const char *expression) { + if( expression && expression[0] ) { + return eval(expression) > 0; + } + return 0; +} + // converts keyboard code to its latin char (if any) char input_keychar(unsigned code) { #define k2(VK,GLFW) [KEY_##VK] = GLFW_KEY_##GLFW diff --git a/engine/split/v4k_input.h b/engine/split/v4k_input.h index 8e6f07c..88371d1 100644 --- a/engine/split/v4k_input.h +++ b/engine/split/v4k_input.h @@ -64,7 +64,9 @@ API bool input_touch_active(); API void input_mappings(const char *filename); // update gamepad mappings (usually "gamecontrollerdb.txt" file) API char input_keychar(unsigned code); // Converts keyboard code to its latin char (if any) +API int input_enum(const char *sym); API int input_anykey(); +API int input_eval(const char *expression); // "down(X)*input(CTRL)" // inject state API void input_send( int vk ); // @todo @@ -115,3 +117,9 @@ enum INPUT_ENUMS { // -- strings: x2 gamepad GAMEPAD_GUID, GAMEPAD_NAME, }; +// these aliases do check both left and right counterparts +enum INPUT_ALIASES { + KEY_SHIFT = KEY_LSHIFT, + KEY_ALT = KEY_LALT, + KEY_CTRL = KEY_LCTRL, +}; diff --git a/engine/split/v4k_ui.c b/engine/split/v4k_ui.c index 71fa145..19a2ac2 100644 --- a/engine/split/v4k_ui.c +++ b/engine/split/v4k_ui.c @@ -76,10 +76,10 @@ static void nk_config_custom_fonts() { // ...with icons embedded on it. static struct icon_font { - const char *file; nk_rune range[3]; + const char *file; int yspacing; nk_rune range[3]; } icons[] = { - {"MaterialIconsSharp-Regular.otf", {UI_ICON_MIN, UI_ICON_MED /*MAX*/, 0}}, // "MaterialIconsOutlined-Regular.otf" "MaterialIcons-Regular.ttf" - {"materialdesignicons-webfont.ttf", {0xF68C /*ICON_MIN_MDI*/, 0xF1C80/*ICON_MAX_MDI*/, 0}}, + {"MaterialIconsSharp-Regular.otf", UI_ICON_SPACING_Y, {UI_ICON_MIN, UI_ICON_MED /*MAX*/, 0}}, // "MaterialIconsOutlined-Regular.otf" "MaterialIcons-Regular.ttf" + {"materialdesignicons-webfont.ttf", 2, {0xF68C /*ICON_MIN_MDI*/, 0xF1CC7/*ICON_MAX_MDI*/, 0}}, }; for( int f = 0; f < countof(icons); ++f ) for( char *data = vfs_load(icons[f].file, &datalen); data; data = 0 ) { @@ -88,7 +88,7 @@ static void nk_config_custom_fonts() { cfg.merge_mode = 1; cfg.spacing.x += UI_ICON_SPACING_X; - cfg.spacing.y += UI_ICON_SPACING_Y; + cfg.spacing.y += icons[f].yspacing; // cfg.font->ascent += ICON_ASCENT; // cfg.font->height += ICON_HEIGHT; @@ -179,6 +179,9 @@ table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = hover_hue; // nk_rgba(255, 0, 0, 255); // table[NK_COLOR_SELECT] = nk_rgba(57, 67, 61, 255); // table[NK_COLOR_SELECT_ACTIVE] = main; +// table[NK_COLOR_SELECT] = nk_rgba(255,255,255,255); +table[NK_COLOR_SELECT_ACTIVE] = main_hue; + // @transparent #if !is(ems) if( glfwGetWindowAttrib(window_handle(), GLFW_TRANSPARENT_FRAMEBUFFER) == GLFW_TRUE ) { @@ -191,6 +194,21 @@ table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = hover_hue; // nk_rgba(255, 0, 0, 255); nk_style_default(ui_ctx); nk_style_from_table(ui_ctx, table); + + if(1) + { + struct nk_style_selectable *select; + select = &ui_ctx->style.selectable; +// nk_zero_struct(*select); +// select->hover.data.color = hover_hue; +// select->normal_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); + select->text_hover = nk_rgba(0,192,255,255); + select->text_hover_active = select->text_hover; + select->text_normal_active = select->text_hover; // nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]).data.color; + select->rounding = 2.0f; + } + + struct nk_style *s = &ui_ctx->style; s->window.spacing = nk_vec2(4,0); s->window.combo_border = 0.f; @@ -1386,14 +1404,20 @@ int ui_panel_end() { } static unsigned ui_collapse_state = 0; +static bool ui_collapse_next_open = 0; int ui_collapse(const char *label, const char *id) { // mask: 0(closed),1(open),2(created) + int open = label[0] == '!'; label += open; uint64_t hash = 14695981039346656037ULL, mult = 0x100000001b3ULL; for(int i = 0; id[i]; ++i) hash = (hash ^ id[i]) * mult; ui_hue = (hash & 0x3F) / (float)0x3F; ui_hue += !ui_hue; - ui_collapse_state = nk_tree_base_(ui_ctx, NK_TREE_NODE, 0, label, NK_MINIMIZED, id, strlen(id), 0); - return ui_collapse_state & 1; // |1 open, |2 clicked, |4 toggled + ui_collapse_state = nk_tree_base_(ui_ctx, NK_TREE_NODE, 0, label, ui_collapse_next_open ? NK_MAXIMIZED : NK_MINIMIZED, id, strlen(id), 0); + return ui_collapse_next_open = 0, ui_collapse_state & 1; // |1 open, |2 clicked, |4 toggled +} +int ui_collapseo(const char *label, const char *id) { // mask: 0(closed),1(open),2(created) + ui_collapse_next_open = true; + return ui_collapse(label, id); } int ui_collapse_clicked() { return ui_collapse_state >> 1; // |1 clicked, |2 toggled @@ -1404,9 +1428,13 @@ int ui_collapse_end() { int ui_contextual() { +#if 0 struct nk_rect bounds = nk_widget_bounds(ui_ctx); // = nk_window_get_bounds(ui_ctx); bounds.y -= 25; return ui_popups() ? 0 : nk_contextual_begin(ui_ctx, 0, nk_vec2(150, 300), bounds); +#else + return ui_popups() ? 0 : nk_contextual_begin(ui_ctx, 0, nk_vec2(300, 220), nk_window_get_bounds(ui_ctx)); +#endif } int ui_contextual_end(int close) { if(close) nk_contextual_close(ui_ctx); @@ -1551,15 +1579,8 @@ int ui_label(const char *text) { nk_layout_row_dynamic(ui_ctx, 0, 1); return ui_label_(text, align); } -int ui_label2(const char *label, const char *text_) { - nk_layout_row_dynamic(ui_ctx, 0, 2); - - int align1 = NK_TEXT_LEFT; - int align2 = NK_TEXT_LEFT; - if( label ) align1 = label[0] == '>' ? (label++, NK_TEXT_RIGHT) : label[0] == '=' ? (label++, NK_TEXT_CENTERED) : label[0] == '<' ? (label++, NK_TEXT_LEFT) : NK_TEXT_LEFT; - if( text_ ) align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT; - ui_label_(label, align1); +static int nk_label_(struct nk_context *ui_ctx, const char *text_, int align2 ) { const struct nk_input *input = &ui_ctx->input; struct nk_rect bounds = nk_widget_bounds(ui_ctx); int is_hovering = nk_input_is_mouse_hovering_rect(input, bounds) && !ui_has_active_popups; @@ -1577,6 +1598,19 @@ ui_label_icon_clicked_R.x = is_hovering ? ( (int)((input->mouse.pos.x - bounds.x return ui_label_icon_clicked_R.x; } + + +int ui_label2(const char *label, const char *text_) { + nk_layout_row_dynamic(ui_ctx, 0, 2); + + int align1 = NK_TEXT_LEFT; + int align2 = NK_TEXT_LEFT; + if( label ) align1 = label[0] == '>' ? (label++, NK_TEXT_RIGHT) : label[0] == '=' ? (label++, NK_TEXT_CENTERED) : label[0] == '<' ? (label++, NK_TEXT_LEFT) : NK_TEXT_LEFT; + if( text_ ) align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT; + ui_label_(label, align1); + + return nk_label_(ui_ctx, text_, align2); +} int ui_label2_bool(const char *text, bool value) { bool b = !!value; return ui_bool(text, &b), 0; @@ -2004,8 +2038,8 @@ int ui_mat44(const char *label, float M[16]) { } int ui_buffer(const char *label, char *buffer, int buflen) { - nk_layout_row_dynamic(ui_ctx, 0, 2); - ui_label_(label, NK_TEXT_LEFT); + nk_layout_row_dynamic(ui_ctx, 0, 1 + (label && label[0])); + if(label && label[0]) ui_label_(label, NK_TEXT_LEFT); int active = nk_edit_string_zero_terminated(ui_ctx, NK_EDIT_AUTO_SELECT|NK_EDIT_CLIPBOARD|NK_EDIT_FIELD/*NK_EDIT_BOX*/|NK_EDIT_SIG_ENTER, buffer, buflen, nk_filter_default); return !!(active & NK_EDIT_COMMITED) ? nk_edit_unfocus(ui_ctx), 1 : 0; diff --git a/engine/split/v4k_ui.h b/engine/split/v4k_ui.h index ef16e1a..11f857a 100644 --- a/engine/split/v4k_ui.h +++ b/engine/split/v4k_ui.h @@ -13,6 +13,7 @@ API int ui_notify(const char *title, const char *body); API int ui_window(const char *title, int *enabled); API int ui_panel(const char *title, int flags); // may be embedded inside a window, or standalone API int ui_collapse(const char *label, const char *id); +API int ui_collapseo(const char *label, const char *id); API int ui_contextual(); API int ui_section(const char *title); API int ui_int(const char *label, int *value); diff --git a/engine/split/v4k_window.c b/engine/split/v4k_window.c index 79a2908..899dc2a 100644 --- a/engine/split/v4k_window.c +++ b/engine/split/v4k_window.c @@ -666,9 +666,9 @@ int window_frame_begin() { ); int choice = ui_toolbar(text); - if( choice == 1 ) editor_send("key_fullscreen",0); - if( choice == 2 ) editor_send("key_screenshot",0); - if( choice == 3 ) editor_send("key_record",0); + if( choice == 1 ) engine_send("key_fullscreen",0); + if( choice == 2 ) engine_send("key_screenshot",0); + if( choice == 3 ) engine_send("key_record",0); } EDITOR_UI_COLLAPSE(ICON_MD_KEYBOARD " Keyboard", "Debug.Keyboard") { ui_keyboard(); @@ -745,8 +745,8 @@ int window_frame_begin() { EDITOR_UI_COLLAPSE(power_icon_label, "Debug.Power") { int choice = ui_toolbar( ICON_MD_POWER ";" ICON_MD_BOLT ); - if( choice == 1 ) editor_send("key_battery","0"); - if( choice == 2 ) editor_send("key_battery","1"); + if( choice == 1 ) engine_send("key_battery","0"); + if( choice == 2 ) engine_send("key_battery","1"); } EDITOR_UI_COLLAPSE(ICON_MD_WATER " Reflection", "Debug.Reflect") { @@ -763,8 +763,8 @@ int window_frame_begin() { (has_menu ? ui_window_end : ui_panel_end)(); } - API int editor_tick(); - editor_tick(); + API int engine_tick(); + engine_tick(); } #endif // ENABLE_RETAIL diff --git a/engine/v4k b/engine/v4k index dcf7503..62f6d8f 100644 --- a/engine/v4k +++ b/engine/v4k @@ -313027,7 +313027,7 @@ API void ProgressiveMesh(int vert_n, int vert_stride, const float *v, int tri_n, /* Other definitions */ #define MAX_ID_LEN 11 /* Max length of an identifier */ -#define OPERATORS "+-*/%(),^" /* Valid operators */ +#define OPERATORS "+-*/%(),^&|!" /* Valid operators */ #define EVAL_PI 3.141592654 #define EVAL_E 2.718281828 @@ -313186,7 +313186,7 @@ start: else if(isalpha(ev->p[0])) { /* Identifier */ int i; - for(i = 0; isalnum(ev->p[0]) && i < MAX_ID_LEN - 1; i++, ev->p++) + for(i = 0; (isalnum(ev->p[0]) || ev->p[0] == '_') && i < MAX_ID_LEN - 1; i++, ev->p++) ev->token[next_tok].s_val[i] = ev->p[0]; if(isalpha(ev->p[0])) longjmp(ev->j, ERR_LONGID); @@ -313233,7 +313233,7 @@ static void expr(struct eval *ev) { static void add_expr(struct eval *ev) { int t; mul_expr(ev); - while((t =EVAL_TYPE(ev)) == '+' || t == '-') { + while((t =EVAL_TYPE(ev)) == '+' || t == '-' || t == '|') { double a,b; lex(ev); mul_expr(ev); @@ -313242,8 +313242,10 @@ static void add_expr(struct eval *ev) { if(t == '+') push(ev, a + b); - else + else if(t == '-') push(ev, a - b); + else + push(ev, a || b); } } @@ -313251,7 +313253,7 @@ static void add_expr(struct eval *ev) { static void mul_expr(struct eval *ev) { int t; pow_expr(ev); - while((t = EVAL_TYPE(ev)) == '*' || t == '/' || t == '%') { + while((t = EVAL_TYPE(ev)) == '*' || t == '/' || t == '%' || t == '&') { double a,b; lex(ev); pow_expr(ev); @@ -313262,8 +313264,10 @@ static void mul_expr(struct eval *ev) { push(ev, a * b); else if(t == '/') push(ev, a / b); - else + else if(t == '%') push(ev, fmod(a, b)); + else + push(ev, a && b); } } @@ -313285,7 +313289,7 @@ static void pow_expr(struct eval *ev) { // uni_expr ::= ['+'|'-'] bra_expr static void uni_expr(struct eval *ev) { int t = '+'; - if(EVAL_TYPE(ev) == '-' || EVAL_TYPE(ev) == '+') { + if(EVAL_TYPE(ev) == '-' || EVAL_TYPE(ev) == '+' || EVAL_TYPE(ev) == '!') { t = EVAL_TYPE(ev); lex(ev); } @@ -313296,6 +313300,10 @@ static void uni_expr(struct eval *ev) { double a = pop(ev); push(ev, -a); } + else if(t == '!') { + double a = pop(ev); + push(ev, !a); + } } // bra_expr ::= '(' add_expr ')' | id_expr @@ -313321,18 +313329,23 @@ static void id_expr(struct eval *ev) { strcpy(id, ev->token[ev->cur_tok].s_val); lex(ev); if(EVAL_TYPE(ev) != '(') { - /**/ if(!istrcmp(id, "true")) push(ev, 1.0); - else if(!istrcmp(id, "false")) push(ev, 0.0); - else if(!istrcmp(id, "on")) push(ev, 1.0); - else if(!istrcmp(id, "off")) push(ev, 0.0); +#ifdef EVAL_EXTEND_CONSTANTS + EVAL_EXTEND_CONSTANTS +#else + if(0) {} +#endif + else if(!strcmp(id, "true")) push(ev, 1.0); + else if(!strcmp(id, "false")) push(ev, 0.0); + else if(!strcmp(id, "on")) push(ev, 1.0); + else if(!strcmp(id, "off")) push(ev, 0.0); // pi - 3.141592654 - else if(!istrcmp(id, "pi")) + else if(!strcmp(id, "pi")) push(ev, EVAL_PI); // e - base of natural logarithms, 2.718281828 - else if(!istrcmp(id, "e")) + else if(!strcmp(id, "e")) push(ev, EVAL_E); // deg - deg2rad, allows to degree conversion `sin(90*deg) = 1` - else if(!istrcmp(id, "deg")) + else if(!strcmp(id, "deg")) push(ev, EVAL_DEG); else EVAL_ERROR(ERR_CONST); @@ -313350,8 +313363,13 @@ static void id_expr(struct eval *ev) { } lex(ev); +#ifdef EVAL_EXTEND_FUNCTIONS + EVAL_EXTEND_FUNCTIONS +#else + if(0) {} +#endif // abs(x) - absolute value of x - if(!istrcmp(id, "abs")) { + else if(!istrcmp(id, "abs")) { if(nargs != 1) EVAL_ERROR(ERR_ARGS); push(ev, fabs(pop(ev))); } diff --git a/engine/v4k.c b/engine/v4k.c index cb57788..bd641fa 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -5802,8 +5802,6 @@ char* vfs_load(const char *pathfile, int *size_out) { // @todo: fix leaks, vfs_u } //} - // PRINTF("VFS: %s\n", pathfile); - int size = 0; void *ptr = 0; @@ -8740,6 +8738,10 @@ void input_update() { any_key |= (bits[i] = glfwGetKeys(win)[ table[i] ]); #endif } + // special cases: plain shift/alt/ctrl enums will also check right counterparts + any_key |= (bits[KEY_ALT] |= glfwGetKey(win, table[KEY_RALT] ) == GLFW_PRESS); + any_key |= (bits[KEY_CTRL] |= glfwGetKey(win, table[KEY_RCTRL] ) == GLFW_PRESS); + any_key |= (bits[KEY_SHIFT] |= glfwGetKey(win, table[KEY_RSHIFT] ) == GLFW_PRESS); #if is(ems) { @@ -8948,6 +8950,35 @@ vec2 input_filter_deadzone_4way( vec2 v, float deadzone ) { return vec2(v0, v1); } +int input_enum(const char *vk) { + static map(char*,int) m = 0; + do_once { + map_init_str(m); + #define k(VK) map_insert(m, STRINGIZE(KEY_##VK), KEY_##VK); map_insert(m, STRINGIZE(VK), KEY_##VK); + k(ESC) + k(TICK) k(1) k(2) k(3) k(4) k(5) k(6) k(7) k(8) k(9) k(0) k(BS) + k(TAB) k(Q) k(W) k(E) k(R) k(T) k(Y) k(U) k(I) k(O) k(P) + k(CAPS) k(A) k(S) k(D) k(F) k(G) k(H) k(J) k(K) k(L) k(ENTER) + k(LSHIFT) k(Z) k(X) k(C) k(V) k(B) k(N) k(M) k(RSHIFT) k(UP) + k(LCTRL) k(LALT) k(SPACE) k(RALT) k(RCTRL) k(LEFT) k(DOWN) k(RIGHT) + + k(F1) k(F2) k(F3) k(F4) k(F5) k(F6) k(F7) k(F8) k(F9) k(F10) k(F11) k(F12) k(PRINT) k(PAUSE) + k(INS) k(HOME) k(PGUP) k(DEL) k(END) k(PGDN) + + k(ALT) k(CTRL) k(SHIFT) + #undef k + }; + int *found = map_find(m, (char*)vk); + return found ? *found : -1; +} + +int input_eval(const char *expression) { + if( expression && expression[0] ) { + return eval(expression) > 0; + } + return 0; +} + // converts keyboard code to its latin char (if any) char input_keychar(unsigned code) { #define k2(VK,GLFW) [KEY_##VK] = GLFW_KEY_##GLFW @@ -20984,10 +21015,10 @@ static void nk_config_custom_fonts() { // ...with icons embedded on it. static struct icon_font { - const char *file; nk_rune range[3]; + const char *file; int yspacing; nk_rune range[3]; } icons[] = { - {"MaterialIconsSharp-Regular.otf", {UI_ICON_MIN, UI_ICON_MED /*MAX*/, 0}}, // "MaterialIconsOutlined-Regular.otf" "MaterialIcons-Regular.ttf" - {"materialdesignicons-webfont.ttf", {0xF68C /*ICON_MIN_MDI*/, 0xF1C80/*ICON_MAX_MDI*/, 0}}, + {"MaterialIconsSharp-Regular.otf", UI_ICON_SPACING_Y, {UI_ICON_MIN, UI_ICON_MED /*MAX*/, 0}}, // "MaterialIconsOutlined-Regular.otf" "MaterialIcons-Regular.ttf" + {"materialdesignicons-webfont.ttf", 2, {0xF68C /*ICON_MIN_MDI*/, 0xF1CC7/*ICON_MAX_MDI*/, 0}}, }; for( int f = 0; f < countof(icons); ++f ) for( char *data = vfs_load(icons[f].file, &datalen); data; data = 0 ) { @@ -20996,7 +21027,7 @@ static void nk_config_custom_fonts() { cfg.merge_mode = 1; cfg.spacing.x += UI_ICON_SPACING_X; - cfg.spacing.y += UI_ICON_SPACING_Y; + cfg.spacing.y += icons[f].yspacing; // cfg.font->ascent += ICON_ASCENT; // cfg.font->height += ICON_HEIGHT; @@ -21087,6 +21118,9 @@ table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = hover_hue; // nk_rgba(255, 0, 0, 255); // table[NK_COLOR_SELECT] = nk_rgba(57, 67, 61, 255); // table[NK_COLOR_SELECT_ACTIVE] = main; +// table[NK_COLOR_SELECT] = nk_rgba(255,255,255,255); +table[NK_COLOR_SELECT_ACTIVE] = main_hue; + // @transparent #if !is(ems) if( glfwGetWindowAttrib(window_handle(), GLFW_TRANSPARENT_FRAMEBUFFER) == GLFW_TRUE ) { @@ -21099,6 +21133,21 @@ table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = hover_hue; // nk_rgba(255, 0, 0, 255); nk_style_default(ui_ctx); nk_style_from_table(ui_ctx, table); + + if(1) + { + struct nk_style_selectable *select; + select = &ui_ctx->style.selectable; +// nk_zero_struct(*select); +// select->hover.data.color = hover_hue; +// select->normal_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); + select->text_hover = nk_rgba(0,192,255,255); + select->text_hover_active = select->text_hover; + select->text_normal_active = select->text_hover; // nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]).data.color; + select->rounding = 2.0f; + } + + struct nk_style *s = &ui_ctx->style; s->window.spacing = nk_vec2(4,0); s->window.combo_border = 0.f; @@ -22294,14 +22343,20 @@ int ui_panel_end() { } static unsigned ui_collapse_state = 0; +static bool ui_collapse_next_open = 0; int ui_collapse(const char *label, const char *id) { // mask: 0(closed),1(open),2(created) + int open = label[0] == '!'; label += open; uint64_t hash = 14695981039346656037ULL, mult = 0x100000001b3ULL; for(int i = 0; id[i]; ++i) hash = (hash ^ id[i]) * mult; ui_hue = (hash & 0x3F) / (float)0x3F; ui_hue += !ui_hue; - ui_collapse_state = nk_tree_base_(ui_ctx, NK_TREE_NODE, 0, label, NK_MINIMIZED, id, strlen(id), 0); - return ui_collapse_state & 1; // |1 open, |2 clicked, |4 toggled + ui_collapse_state = nk_tree_base_(ui_ctx, NK_TREE_NODE, 0, label, ui_collapse_next_open ? NK_MAXIMIZED : NK_MINIMIZED, id, strlen(id), 0); + return ui_collapse_next_open = 0, ui_collapse_state & 1; // |1 open, |2 clicked, |4 toggled +} +int ui_collapseo(const char *label, const char *id) { // mask: 0(closed),1(open),2(created) + ui_collapse_next_open = true; + return ui_collapse(label, id); } int ui_collapse_clicked() { return ui_collapse_state >> 1; // |1 clicked, |2 toggled @@ -22312,9 +22367,13 @@ int ui_collapse_end() { int ui_contextual() { +#if 0 struct nk_rect bounds = nk_widget_bounds(ui_ctx); // = nk_window_get_bounds(ui_ctx); bounds.y -= 25; return ui_popups() ? 0 : nk_contextual_begin(ui_ctx, 0, nk_vec2(150, 300), bounds); +#else + return ui_popups() ? 0 : nk_contextual_begin(ui_ctx, 0, nk_vec2(300, 220), nk_window_get_bounds(ui_ctx)); +#endif } int ui_contextual_end(int close) { if(close) nk_contextual_close(ui_ctx); @@ -22459,15 +22518,8 @@ int ui_label(const char *text) { nk_layout_row_dynamic(ui_ctx, 0, 1); return ui_label_(text, align); } -int ui_label2(const char *label, const char *text_) { - nk_layout_row_dynamic(ui_ctx, 0, 2); - - int align1 = NK_TEXT_LEFT; - int align2 = NK_TEXT_LEFT; - if( label ) align1 = label[0] == '>' ? (label++, NK_TEXT_RIGHT) : label[0] == '=' ? (label++, NK_TEXT_CENTERED) : label[0] == '<' ? (label++, NK_TEXT_LEFT) : NK_TEXT_LEFT; - if( text_ ) align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT; - ui_label_(label, align1); +static int nk_label_(struct nk_context *ui_ctx, const char *text_, int align2 ) { const struct nk_input *input = &ui_ctx->input; struct nk_rect bounds = nk_widget_bounds(ui_ctx); int is_hovering = nk_input_is_mouse_hovering_rect(input, bounds) && !ui_has_active_popups; @@ -22485,6 +22537,19 @@ ui_label_icon_clicked_R.x = is_hovering ? ( (int)((input->mouse.pos.x - bounds.x return ui_label_icon_clicked_R.x; } + + +int ui_label2(const char *label, const char *text_) { + nk_layout_row_dynamic(ui_ctx, 0, 2); + + int align1 = NK_TEXT_LEFT; + int align2 = NK_TEXT_LEFT; + if( label ) align1 = label[0] == '>' ? (label++, NK_TEXT_RIGHT) : label[0] == '=' ? (label++, NK_TEXT_CENTERED) : label[0] == '<' ? (label++, NK_TEXT_LEFT) : NK_TEXT_LEFT; + if( text_ ) align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT; + ui_label_(label, align1); + + return nk_label_(ui_ctx, text_, align2); +} int ui_label2_bool(const char *text, bool value) { bool b = !!value; return ui_bool(text, &b), 0; @@ -22912,8 +22977,8 @@ int ui_mat44(const char *label, float M[16]) { } int ui_buffer(const char *label, char *buffer, int buflen) { - nk_layout_row_dynamic(ui_ctx, 0, 2); - ui_label_(label, NK_TEXT_LEFT); + nk_layout_row_dynamic(ui_ctx, 0, 1 + (label && label[0])); + if(label && label[0]) ui_label_(label, NK_TEXT_LEFT); int active = nk_edit_string_zero_terminated(ui_ctx, NK_EDIT_AUTO_SELECT|NK_EDIT_CLIPBOARD|NK_EDIT_FIELD/*NK_EDIT_BOX*/|NK_EDIT_SIG_ENTER, buffer, buflen, nk_filter_default); return !!(active & NK_EDIT_COMMITED) ? nk_edit_unfocus(ui_ctx), 1 : 0; @@ -24332,9 +24397,9 @@ int window_frame_begin() { ); int choice = ui_toolbar(text); - if( choice == 1 ) editor_send("key_fullscreen",0); - if( choice == 2 ) editor_send("key_screenshot",0); - if( choice == 3 ) editor_send("key_record",0); + if( choice == 1 ) engine_send("key_fullscreen",0); + if( choice == 2 ) engine_send("key_screenshot",0); + if( choice == 3 ) engine_send("key_record",0); } EDITOR_UI_COLLAPSE(ICON_MD_KEYBOARD " Keyboard", "Debug.Keyboard") { ui_keyboard(); @@ -24411,8 +24476,8 @@ int window_frame_begin() { EDITOR_UI_COLLAPSE(power_icon_label, "Debug.Power") { int choice = ui_toolbar( ICON_MD_POWER ";" ICON_MD_BOLT ); - if( choice == 1 ) editor_send("key_battery","0"); - if( choice == 2 ) editor_send("key_battery","1"); + if( choice == 1 ) engine_send("key_battery","0"); + if( choice == 2 ) engine_send("key_battery","1"); } EDITOR_UI_COLLAPSE(ICON_MD_WATER " Reflection", "Debug.Reflect") { @@ -24429,8 +24494,8 @@ int window_frame_begin() { (has_menu ? ui_window_end : ui_panel_end)(); } - API int editor_tick(); - editor_tick(); + API int engine_tick(); + engine_tick(); } #endif // ENABLE_RETAIL @@ -26708,6 +26773,7 @@ vec3 editor_pick(float mouse_x, float mouse_y) { #endif } +#if 0 int editor_ui_bits8(const char *label, uint8_t *enabled) { // @to deprecate int clicked = 0; uint8_t copy = *enabled; @@ -26741,37 +26807,37 @@ int editor_ui_bits8(const char *label, uint8_t *enabled) { // @to deprecate nk_layout_row_end(ui_ctx); return clicked | (copy ^ *enabled); } +#endif - -typedef union editor_var { +typedef union engine_var { int i; float f; char *s; -} editor_var; -static map(char*,editor_var) editor_vars; -float *editor_getf(const char *key) { - if(!editor_vars) map_init_str(editor_vars); - editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) ); +} engine_var; +static map(char*,engine_var) engine_vars; +float *engine_getf(const char *key) { + if(!engine_vars) map_init_str(engine_vars); + engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); return &found->f; } -int *editor_geti(const char *key) { - if(!editor_vars) map_init_str(editor_vars); - editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) ); +int *engine_geti(const char *key) { + if(!engine_vars) map_init_str(engine_vars); + engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); return &found->i; } -char **editor_gets(const char *key) { - if(!editor_vars) map_init_str(editor_vars); - editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) ); +char **engine_gets(const char *key) { + if(!engine_vars) map_init_str(engine_vars); + engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); if(!found->s) found->s = stringf("%s",""); return &found->s; } -int editor_send(const char *cmd, const char *optional_value) { - unsigned *gamepads = editor_geti("gamepads"); // 0 off, mask gamepad1(1), gamepad2(2), gamepad3(4), gamepad4(8)... - unsigned *renders = editor_geti("renders"); // 0 off, mask: 1=lit, 2=ddraw, 3=whiteboxes - float *speed = editor_getf("speed"); // <0 num of frames to advance, 0 paused, [0..1] slomo, 1 play regular speed, >1 fast-forward (x2/x4/x8) - unsigned *powersave = editor_geti("powersave"); +int engine_send(const char *cmd, const char *optional_value) { + unsigned *gamepads = engine_geti("gamepads"); // 0 off, mask gamepad1(1), gamepad2(2), gamepad3(4), gamepad4(8)... + unsigned *renders = engine_geti("renders"); // 0 off, mask: 1=lit, 2=ddraw, 3=whiteboxes + float *speed = engine_getf("speed"); // <0 num of frames to advance, 0 paused, [0..1] slomo, 1 play regular speed, >1 fast-forward (x2/x4/x8) + unsigned *powersave = engine_geti("powersave"); char *name; /**/ if( !strcmp(cmd, "key_quit" )) record_stop(), exit(0); @@ -26795,14 +26861,14 @@ int editor_send(const char *cmd, const char *optional_value) { return 0; } -int editor_tick() { - enum { editor_hz = 60 }; - enum { editor_hz_mid = 18 }; - enum { editor_hz_low = 5 }; - if( *editor_geti("powersave") ) { +int engine_tick() { + enum { engine_hz = 60 }; + enum { engine_hz_mid = 18 }; + enum { engine_hz_low = 5 }; + if( *engine_geti("powersave") ) { // adaptive framerate int app_on_background = !window_has_focus(); - int hz = app_on_background ? editor_hz_low : editor_hz_mid; + int hz = app_on_background ? engine_hz_low : engine_hz_mid; window_fps_lock( hz < 5 ? 5 : hz ); } else { // window_fps_lock( editor_hz ); diff --git a/engine/v4k.h b/engine/v4k.h index 789822d..328cfcd 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -1783,17 +1783,17 @@ API void* dll(const char *filename, const char *symbol); // in-game editor // - rlyeh, public domain. // -// @todo: merge editor1.c and editor2.c internals into this api +// @todo: merge editor1.c and editor3.c internals into this api //API void editor(); //API bool editor_active(); API vec3 editor_pick(float mouse_x, float mouse_y); API char* editor_path(const char *path); -API float* editor_getf(const char *key); -API int* editor_geti(const char *key); -API char** editor_gets(const char *key); -API int editor_send(const char *cmd, const char *optional_value); +API float* engine_getf(const char *key); +API int* engine_geti(const char *key); +API char** engine_gets(const char *key); +API int engine_send(const char *cmd, const char *optional_value); // open file dialog @@ -1808,19 +1808,19 @@ API bool gizmo_hover(); // localization kit (I18N, L10N) -API void kit_locale( const char *langcode_iso639_1 ); // set context language: enUS, ptBR, esES, ... -API void kit_set( const char *variable, const char *value ); // set context variable -API void kit_reset(); // reset all variables in context - -API void kit_insert( const char *id, const char *translation ); // insert single translation API bool kit_load( const char *filename ); // load translations file (xlsx) API bool kit_merge( const char *filename ); // merge translations file into existing context +API void kit_insert( const char *id, const char *translation ); // insert single translation unit API void kit_clear(); // delete all translations -API char* kit_translate( const char *id ); // perform a translation, given current locale +API void kit_set( const char *variable, const char *value ); // set context variable +API void kit_reset(); // reset all variables in context +API void kit_dump_state( FILE *fp ); // debug + API char* kit_translate2( const char *id, const char *langcode_iso639_1 ); // perform a translation given explicit locale -API void kit_dump_state( FILE *fp ); +API void kit_locale( const char *langcode_iso639_1 ); // set current locale: enUS, ptBR, esES, ... +API char* kit_translate( const char *id ); // perform a translation, given current locale #line 0 #line 1 "engine/split/v4k_file.h" @@ -2412,7 +2412,9 @@ API bool input_touch_active(); API void input_mappings(const char *filename); // update gamepad mappings (usually "gamecontrollerdb.txt" file) API char input_keychar(unsigned code); // Converts keyboard code to its latin char (if any) +API int input_enum(const char *sym); API int input_anykey(); +API int input_eval(const char *expression); // "down(X)*input(CTRL)" // inject state API void input_send( int vk ); // @todo @@ -2463,6 +2465,12 @@ enum INPUT_ENUMS { // -- strings: x2 gamepad GAMEPAD_GUID, GAMEPAD_NAME, }; +// these aliases do check both left and right counterparts +enum INPUT_ALIASES { + KEY_SHIFT = KEY_LSHIFT, + KEY_ALT = KEY_LALT, + KEY_CTRL = KEY_LCTRL, +}; #line 0 #line 1 "engine/split/v4k_memory.h" @@ -4274,6 +4282,7 @@ API int ui_notify(const char *title, const char *body); API int ui_window(const char *title, int *enabled); API int ui_panel(const char *title, int flags); // may be embedded inside a window, or standalone API int ui_collapse(const char *label, const char *id); +API int ui_collapseo(const char *label, const char *id); API int ui_contextual(); API int ui_section(const char *title); API int ui_int(const char *label, int *value);