diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-03-21 16:45:26 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-03-21 16:45:26 +0000 |
| commit | faa13fe70371834c3e7e234875d32bb95d278c54 (patch) | |
| tree | 2a1e52d2fde94993a9ea787dadeaec8416912f49 /src/game | |
| parent | a339dcf731278656a57aceec02696b752e85f7b6 (diff) | |
| download | zcatch-faa13fe70371834c3e7e234875d32bb95d278c54.tar.gz zcatch-faa13fe70371834c3e7e234875d32bb95d278c54.zip | |
fixed input problems. made better input in console and chat
Diffstat (limited to 'src/game')
| -rw-r--r-- | src/game/client/gc_client.cpp | 217 | ||||
| -rw-r--r-- | src/game/client/gc_client.h | 47 | ||||
| -rw-r--r-- | src/game/client/gc_console.cpp | 161 | ||||
| -rw-r--r-- | src/game/client/gc_console.h | 9 | ||||
| -rw-r--r-- | src/game/client/gc_hooks.cpp | 22 | ||||
| -rw-r--r-- | src/game/client/gc_menu.cpp | 23 | ||||
| -rw-r--r-- | src/game/client/gc_ui.cpp | 4 |
7 files changed, 297 insertions, 186 deletions
diff --git a/src/game/client/gc_client.cpp b/src/game/client/gc_client.cpp index 80e7bd40..552ca252 100644 --- a/src/game/client/gc_client.cpp +++ b/src/game/client/gc_client.cpp @@ -197,10 +197,26 @@ void render_damage_indicators() dmgind.render(); } -static char chat_input[512]; -static unsigned chat_input_len; +static line_input chat_input; static const int chat_max_lines = 10; +bool chat_input_handle(INPUT_EVENT e, void *user_data) +{ + if(chat_mode == CHATMODE_NONE) + return false; + + if(e.flags&INPFLAG_PRESS && (e.key == KEY_ENTER || e.key == KEY_KP_ENTER)) + { + if(chat_input.get_string()[0]) + chat_say(chat_mode == CHATMODE_ALL ? 0 : 1, chat_input.get_string()); + chat_mode = CHATMODE_NONE; + } + else + chat_input.process_input(e); + + return true; +} + struct chatline { int tick; @@ -263,6 +279,101 @@ int killmsg_current = 0; //bool add_trail = false; +line_input::line_input() +{ + clear(); +} + +void line_input::clear() +{ + mem_zero(str, sizeof(str)); + len = 0; + cursor_pos = 0; +} + +void line_input::set(const char *string) +{ + str_copy(str, string, sizeof(str)); + len = strlen(str); + cursor_pos = len; +} + +void line_input::process_input(INPUT_EVENT e) +{ + if(cursor_pos > len) + cursor_pos = len; + + char c = e.ch; + int k = e.key; + + if (!(c >= 0 && c < 32)) + { + if (len < sizeof(str) - 1 && cursor_pos < sizeof(str) - 1) + { + memmove(str + cursor_pos + 1, str + cursor_pos, len - cursor_pos + 1); + str[cursor_pos] = c; + cursor_pos++; + len++; + } + } + + if(e.flags&INPFLAG_PRESS) + { + if (k == KEY_BACKSPACE && cursor_pos > 0) + { + memmove(str + cursor_pos - 1, str + cursor_pos, len - cursor_pos + 1); + cursor_pos--; + len--; + } + else if (k == KEY_DEL && cursor_pos < len) + { + memmove(str + cursor_pos, str + cursor_pos + 1, len - cursor_pos); + len--; + } + else if (k == KEY_LEFT && cursor_pos > 0) + cursor_pos--; + else if (k == KEY_RIGHT && cursor_pos < len) + cursor_pos++; + else if (k == KEY_HOME) + cursor_pos = 0; + else if (k == KEY_END) + cursor_pos = len; + } +} + +input_stack_handler::input_stack_handler() +{ + num_handlers = 0; +} + +void input_stack_handler::add_handler(callback cb, void *user) +{ + user_data[num_handlers] = user; + handlers[num_handlers++] = cb; +} + +void input_stack_handler::dispatch_input() +{ + for(int i = 0; i < inp_num_events(); i++) + { + INPUT_EVENT e = inp_get_event(i); + + for(int h = 0; h < num_handlers; h++) + { + if(handlers[h](e, user_data[h])) + { + //dbg_msg("", "%d char=%d key=%d flags=%d", h, e.ch, e.key, e.flags); + break; + } + } + } + + inp_clear_events(); +} + + +input_stack_handler input_stack; + extern int render_popup(const char *caption, const char *text, const char *button_text); void process_events(int snaptype) @@ -738,12 +849,8 @@ void chat_enable_mode(int team) chat_mode = CHATMODE_TEAM; else chat_mode = CHATMODE_ALL; - - mem_zero(chat_input, sizeof(chat_input)); - chat_input_len = 0; - // make sure that we don't trigger something weird - inp_clear_events(); + chat_input.clear(); } } @@ -804,51 +911,6 @@ void render_game() menu_was_active = false; } - // handle chat input - if (!menu_active) - { - if(chat_mode != CHATMODE_NONE) - { - for(int i = 0; i < inp_num_events(); i++) - { - INPUT_EVENT e = inp_get_event(i); - - if(e.ch >= 32) - { - if (chat_input_len < sizeof(chat_input) - 1) - { - chat_input[chat_input_len] = e.ch; - chat_input[chat_input_len+1] = 0; - chat_input_len++; - } - } - - if((e.key == KEY_ENTER || e.key == KEY_KP_ENTER) && (e.flags&INPFLAG_PRESS)) - { - // send message - if(chat_input_len) - chat_say(chat_mode == CHATMODE_ALL ? 0 : 1, chat_input); - - chat_mode = CHATMODE_NONE; - break; - } - - if(e.key == KEY_BACKSPACE && (e.flags&INPFLAG_PRESS)) - { - if(chat_input_len > 0) - { - chat_input[chat_input_len-1] = 0; - chat_input_len--; - } - } - } - } - } - - if (!menu_active) - inp_clear_events(); - - // float camera_max_distance = 250.0f; float deadzone = config.cl_mouse_deadzone; @@ -1191,19 +1253,24 @@ void render_game() gfx_mapscreen(0,0,300*gfx_screenaspect(),300); float x = 10.0f; float y = 300.0f-30.0f; - float starty = -1; if(chat_mode != CHATMODE_NONE) { // render chat input - char buf[sizeof(chat_input)+16]; + TEXT_CURSOR cursor; + gfx_text_set_cursor(&cursor, x, y, 8.0f, TEXTFLAG_RENDER); + cursor.line_width = 300.0f; + if(chat_mode == CHATMODE_ALL) - str_format(buf, sizeof(buf), "All: %s_", chat_input); + gfx_text_ex(&cursor, "All: ", -1); else if(chat_mode == CHATMODE_TEAM) - str_format(buf, sizeof(buf), "Team: %s_", chat_input); + gfx_text_ex(&cursor, "Team: ", -1); else - str_format(buf, sizeof(buf), "Chat: %s_", chat_input); - gfx_text(0, x, y, 8.0f, buf, 380); - starty = y; + gfx_text_ex(&cursor, "Chat: ", -1); + + gfx_text_ex(&cursor, chat_input.get_string(), chat_input.cursor_offset()); + TEXT_CURSOR marker = cursor; + gfx_text_ex(&marker, "|", -1); + gfx_text_ex(&cursor, chat_input.get_string()+chat_input.cursor_offset(), -1); } y -= 8; @@ -1216,16 +1283,19 @@ void render_game() break; float begin = x; - - float fontsize = 8.0f; - // turn of alpha so we can render once and just get the number of lines - // TODO: this is ugly, but have to do for now - gfx_text_color(1,1,1,0); - int lines = gfx_text(0, begin, y, fontsize, chat_lines[r].text, 300); - - y -= fontsize * (lines); + // get the y offset + TEXT_CURSOR cursor; + gfx_text_set_cursor(&cursor, begin, 0, fontsize, 0); + cursor.line_width = 300.0f; + gfx_text_ex(&cursor, chat_lines[r].name, -1); + gfx_text_ex(&cursor, chat_lines[r].text, -1); + y -= cursor.y + cursor.font_size; + + // reset the cursor + gfx_text_set_cursor(&cursor, begin, y, fontsize, TEXTFLAG_RENDER); + cursor.line_width = 300.0f; // render name gfx_text_color(0.8f,0.8f,0.8f,1); @@ -1240,22 +1310,17 @@ void render_game() else if(chat_lines[r].name_color == -1) gfx_text_color(0.75f,0.5f,0.75f, 1); // spectator - // render line - - //int lines = int(gfx_text_width(0, fontsize, chat_lines[r].text, -1)) / 300 + 1; - - - gfx_text(0, begin, y, fontsize, chat_lines[r].name, -1); - begin += gfx_text_width(0, fontsize, chat_lines[r].name, -1); - + // render name + gfx_text_ex(&cursor, chat_lines[r].name, -1); + // render line gfx_text_color(1,1,1,1); if(chat_lines[r].client_id == -1) gfx_text_color(1,1,0.5f,1); // system else if(chat_lines[r].team) gfx_text_color(0.65f,1,0.65f,1); // team message - gfx_text(0, begin, y, fontsize, chat_lines[r].text, 300); + gfx_text_ex(&cursor, chat_lines[r].text, -1); } gfx_text_color(1,1,1,1); diff --git a/src/game/client/gc_client.h b/src/game/client/gc_client.h index 7ba8a32a..6e63ce6f 100644 --- a/src/game/client/gc_client.h +++ b/src/game/client/gc_client.h @@ -82,6 +82,53 @@ enum extern int chat_mode; void chat_add_line(int client_id, int team, const char *line); void chat_reset(); +bool chat_input_handle(INPUT_EVENT e, void *user_data); + +// line input helter +class line_input +{ + char str[256]; + unsigned len; + unsigned cursor_pos; +public: + class callback + { + public: + virtual ~callback() {} + virtual bool event(INPUT_EVENT e) = 0; + }; + + line_input(); + void clear(); + void process_input(INPUT_EVENT e); + void set(const char *string); + const char *get_string() const { return str; } + int get_length() const { return len; } + unsigned cursor_offset() const { return cursor_pos; } +}; + +class input_stack_handler +{ +public: + typedef bool (*callback)(INPUT_EVENT e, void *user); + + input_stack_handler(); + void add_handler(callback cb, void *user_data); + void dispatch_input(); + +private: + enum + { + MAX_HANDLERS=16 + }; + + callback handlers[MAX_HANDLERS]; + void *user_data[MAX_HANDLERS]; + int num_handlers; +}; + +extern input_stack_handler input_stack; + extern int emoticon_selector_active; // TODO: ugly extern int scoreboard_active; // TODO: ugly diff --git a/src/game/client/gc_console.cpp b/src/game/client/gc_console.cpp index ca1e20cb..19ad6d63 100644 --- a/src/game/client/gc_console.cpp +++ b/src/game/client/gc_console.cpp @@ -36,18 +36,14 @@ public: char backlog_data[65536]; RINGBUFFER *backlog; - unsigned int input_len; - char input[256]; + + line_input input; int type; public: CONSOLE(int t) { - // clear input - input_len = 0; - mem_zero(input, sizeof(input)); - // init ringbuffers history = ringbuf_init(history_data, sizeof(history_data)); backlog = ringbuf_init(backlog_data, sizeof(backlog_data)); @@ -72,43 +68,23 @@ public: void handle_event(INPUT_EVENT e) { - if (e.ch >= 32) - { - if (input_len < sizeof(input) - 1) - { - input[input_len] = e.ch; - input[input_len+1] = 0; - input_len++; - - history_entry = 0x0; - } - } - + bool handled = false; + if(e.flags&INPFLAG_PRESS) { - if(e.key == KEY_BACKSPACE) - { - if(input_len > 0) - { - input[input_len-1] = 0; - input_len--; - - history_entry = 0x0; - } - } - else if(e.key == KEY_ENTER || e.key == KEY_KP_ENTER) + if(e.key == KEY_ENTER || e.key == KEY_KP_ENTER) { - if (input_len) + if(input.get_string()[0]) { - char *entry = (char *)ringbuf_allocate(history, input_len+1); - mem_copy(entry, input, input_len+1); + char *entry = (char *)ringbuf_allocate(history, input.get_length()+1); + mem_copy(entry, input.get_string(), input.get_length()+1); - execute_line(input); - input[0] = 0; - input_len = 0; - + execute_line(input.get_string()); + input.clear(); history_entry = 0x0; } + + handled = true; } else if (e.key == KEY_UP) { @@ -126,12 +102,9 @@ public: { unsigned int len = strlen(history_entry); if (len < sizeof(input) - 1) - { - mem_copy(input, history_entry, len+1); - input_len = len; - } + input.set(history_entry); } - + handled = true; } else if (e.key == KEY_DOWN) { @@ -142,19 +115,16 @@ public: { unsigned int len = strlen(history_entry); if (len < sizeof(input) - 1) - { - mem_copy(input, history_entry, len+1); - - input_len = len; - } + input.set(history_entry); } else - { - input[0] = 0; - input_len = 0; - } + input.clear(); + handled = true; } } + + if(!handled) + input.process_input(e); } void print_line(const char *line) @@ -426,38 +396,37 @@ void client_console_init() binds_set('Y', "chat team"); } -void console_handle_input() +bool console_input_cli(INPUT_EVENT e, void *user_data) { - int was_active = console_active(); + if(!console_active()) + return false; + + if(e.key == KEY_ESC && (e.flags&INPFLAG_PRESS)) + console_toggle(console_type); + else + current_console()->handle_event(e); + return true; +} - for(int i = 0; i < inp_num_events(); i++) - { - INPUT_EVENT e = inp_get_event(i); - - if(console_active()) - { - if(e.key == KEY_ESC && e.flags&INPFLAG_PRESS) - console_toggle(console_type); - else - current_console()->handle_event(e); - } - else - { - if(e.key > 0 && e.key < KEY_LAST && keybindings[e.key][0] != 0) - { - int stroke = 0; - if(e.flags&INPFLAG_PRESS) - stroke = 1; - console_execute_line_stroked(stroke, keybindings[e.key]); - } - } - } +bool console_input_special_binds(INPUT_EVENT e, void *user_data) +{ + // only handle function keys + if(e.key < KEY_F1 || e.key > KEY_F25) + return false; + return console_input_normal_binds(e, user_data); +} - if(was_active || console_active()) - { - inp_clear_events(); - inp_clear_key_states(); - } +bool console_input_normal_binds(INPUT_EVENT e, void *user_data) +{ + // don't handle invalid events and keys that arn't set to anything + if(e.key <= 0 || e.key >= KEY_LAST || keybindings[e.key][0] == 0) + return false; + + int stroke = 0; + if(e.flags&INPFLAG_PRESS) + stroke = 1; + console_execute_line_stroked(stroke, keybindings[e.key]); + return true; } void console_toggle(int type) @@ -575,30 +544,38 @@ void console_render() { float font_size = 10.0f; float row_height = font_size*1.25f; - float width = gfx_text_width(0, font_size, console->input, -1); - float x = 3, y = console_height - row_height - 2; - const char *prompt = ">"; + float x = 3; + float y = console_height - row_height - 2; + + // render prompt + TEXT_CURSOR cursor; + gfx_text_set_cursor(&cursor, x, y, font_size, TEXTFLAG_RENDER); + + const char *prompt = "> "; if(console_type) { if(client_rcon_authed()) - prompt = "rcon>"; + prompt = "rcon> "; else - prompt = "rcon password>"; + prompt = "rcon password> "; } - - float prompt_width = gfx_text_width(0, font_size,prompt, -1)+2; - - gfx_text(0, x, y, font_size, prompt, -1); - gfx_text(0, x+prompt_width, y, font_size, console->input, -1); - gfx_text(0, x+prompt_width+width+1, y, font_size, "_", -1); + gfx_text_ex(&cursor, prompt, -1); + + // render console input + gfx_text_ex(&cursor, console->input.get_string(), console->input.cursor_offset()); + TEXT_CURSOR marker = cursor; + gfx_text_ex(&marker, "|", -1); + gfx_text_ex(&cursor, console->input.get_string()+console->input.cursor_offset(), -1); + + // render version char buf[128]; - str_format(buf, sizeof(buf), "Teewars v%s %s", TEEWARS_VERSION); + str_format(buf, sizeof(buf), "Teewars v%s", TEEWARS_VERSION); float version_width = gfx_text_width(0, font_size, buf, -1); gfx_text(0, screen.w-version_width-5, y, font_size, buf, -1); + // render log y -= row_height; - char *entry = (char *)ringbuf_last(console->backlog); while (y > 0.0f && entry) { diff --git a/src/game/client/gc_console.h b/src/game/client/gc_console.h index 0d516820..b75d7646 100644 --- a/src/game/client/gc_console.h +++ b/src/game/client/gc_console.h @@ -1,7 +1,14 @@ #ifndef _GC_CONSOLE_H #define _GC_CONSOLE_H -void console_handle_input(); +#include <engine/e_client_interface.h> + +bool console_input_cli(INPUT_EVENT e, void *user_data); +bool console_input_special_binds(INPUT_EVENT e, void *user_data); +bool console_input_normal_binds(INPUT_EVENT e, void *user_data); + +//void console_handle_input(); + void console_toggle(int tpye); void console_render(); int console_active(); diff --git a/src/game/client/gc_hooks.cpp b/src/game/client/gc_hooks.cpp index 021228c1..2d9a1ba3 100644 --- a/src/game/client/gc_hooks.cpp +++ b/src/game/client/gc_hooks.cpp @@ -52,15 +52,14 @@ extern "C" void modc_init() static FONT_SET default_font; int64 start = time_get(); - vec2 v; - v = closest_point_on_line(vec2(0, 0), vec2(10, 0), vec2(5, 0)); - dbg_msg("", "1: %f,%f", v.x, v.y); - v = closest_point_on_line(vec2(0, 0), vec2(20, 0), vec2(5, 0)); - dbg_msg("", "2: %f,%f", v.x, v.y); - v = closest_point_on_line(vec2(0, 0), vec2(10, 0), vec2(20, 0)); - dbg_msg("", "3: %f,%f", v.x, v.y); + // setup input stack + input_stack.add_handler(console_input_special_binds, 0); // F1-Fx binds + input_stack.add_handler(console_input_cli, 0); // console + input_stack.add_handler(chat_input_handle, 0); // chat + //input_stack.add_handler() // ui + input_stack.add_handler(console_input_normal_binds, 0); // binds + - int before = gfx_memory_usage(); font_set_load(&default_font, "data/fonts/default_font%d.tfnt", "data/fonts/default_font%d.png", "data/fonts/default_font%d_b.png", 14, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 36); dbg_msg("font", "gfx memory used for font textures: %d", gfx_memory_usage()-before); @@ -352,18 +351,13 @@ extern "C" void modc_newsnapshot() extern "C" void modc_render() { - console_handle_input(); - // this should be moved around abit if(client_state() == CLIENTSTATE_ONLINE) - { render_game(); - } else - { menu_render(); - } + input_stack.dispatch_input(); console_render(); } diff --git a/src/game/client/gc_menu.cpp b/src/game/client/gc_menu.cpp index 82c17ab1..90a39491 100644 --- a/src/game/client/gc_menu.cpp +++ b/src/game/client/gc_menu.cpp @@ -2069,6 +2069,27 @@ void menu_render() static int mouse_x = 0; static int mouse_y = 0; + /* + RECT screen = *ui_screen(); + gfx_mapscreen(screen.x, screen.y, screen.w, screen.h); + menu2_render_background(); + + TEXT_CURSOR cursor; + mem_zero(&cursor, sizeof(cursor)); + cursor.font_size = 32.0f; + cursor.start_x = 10.0f; + cursor.start_y = 10.0f; + cursor.x = cursor.start_x; + cursor.y = cursor.start_y; + cursor.line_count = 1; + cursor.line_width = 200.0f; + cursor.flags = TEXTFLAG_RENDER; + + gfx_text_new(&cursor, "The quick brown fox jumped over the lazy dog.", -1); + + DEBUG_text = 0; + return;*/ + // update colors vec3 rgb = hsl_to_rgb(vec3(config.ui_color_hue/255.0f, config.ui_color_sat/255.0f, config.ui_color_lht/255.0f)); @@ -2124,6 +2145,4 @@ void menu_render() gfx_setcolor(1,1,1,1); gfx_quads_drawTL(mx,my,24,24); gfx_quads_end(); - - inp_clear_events(); } diff --git a/src/game/client/gc_ui.cpp b/src/game/client/gc_ui.cpp index a7580d5d..dc78c0ca 100644 --- a/src/game/client/gc_ui.cpp +++ b/src/game/client/gc_ui.cpp @@ -45,7 +45,9 @@ int ui_update(float mx, float my, float mwx, float mwy, int buttons) becomming_hot_item = 0; return 0; } - +/* +bool ui_ +*/ int ui_mouse_inside(const RECT *r) { if(mouse_x >= r->x && mouse_x <= r->x+r->w && mouse_y >= r->y && mouse_y <= r->y+r->h) |