diff --git a/source/src/console.cpp b/source/src/console.cpp index 2c26b169..8c7beed2 100644 --- a/source/src/console.cpp +++ b/source/src/console.cpp @@ -83,13 +83,6 @@ void rendercommand(int x, int y) // keymap is defined externally in keymap.cfg -struct keym -{ - int code; - char *name, *action; - - ~keym() { DELETEA(name); DELETEA(action); } -}; vector keyms; void keymap(char *code, char *key, char *action) @@ -100,26 +93,54 @@ void keymap(char *code, char *key, char *action) km.action = newstring(action); } + + COMMAND(keymap, ARG_3STR); keym *findbind(char *key) { loopv(keyms) if(!strcasecmp(keyms[i].name, key)) return &keyms[i]; return NULL; -} +} + +keym *findbinda(char *action) +{ + loopv(keyms) if(!strcasecmp(keyms[i].action, action)) return &keyms[i]; + return NULL; +} + +keym *findbindc(int code) +{ + loopv(keyms) if(keyms[i].code==code) return &keyms[i]; + return NULL; +} keym *keypressed = NULL; char *keyaction = NULL; -void bindkey(char *key, char *action) +bool bindkey(keym *km, char *action) +{ + if(!km) return false; + if(!keypressed || keyaction!=km->action) delete[] km->action; + km->action = newstring(action); + return true; +} + +void bindk(char *key, char *action) { keym *km = findbind(key); if(!km) { conoutf("unknown key \"%s\"", key); return; } - if(!keypressed || keyaction!=km->action) delete[] km->action; - km->action = newstring(action); + bindkey(km, action); } -COMMANDN(bind, bindkey, ARG_2STR); +bool bindc(int code, char *action) +{ + keym *km = findbindc(code); + if(km) return bindkey(km, action); + else return false; +} + +COMMANDN(bind, bindk, ARG_2STR); struct releaseaction { diff --git a/source/src/menus.cpp b/source/src/menus.cpp index 56e93042..973e4097 100644 --- a/source/src/menus.cpp +++ b/source/src/menus.cpp @@ -102,7 +102,7 @@ void gmenu::open() if(allowinput) player1->stopmoving(); else menusel = 0; if(items.inrange(menusel)) items[menusel]->focus(true); - loopv(items) items[i]->init(); + init(); } void gmenu::close() @@ -110,6 +110,8 @@ void gmenu::close() if(items.inrange(menusel)) items[menusel]->focus(false); } +void gmenu::init() { loopv(items) items[i]->init(); } + void gmenu::render() { const char *t = title; @@ -176,7 +178,7 @@ void mitem::render(int x, int y, int w) void mitem::renderbg(int x, int y, int w) { blendbox(x-FONTH, y-FONTH/6, x+w+FONTH, y+FONTH+FONTH/6, false, -1, bgcolor); }; -bool mitem::isselection() { return parent->items.inrange(parent->menusel) && parent->items[parent->menusel]==this; } +bool mitem::isselection() { return parent->allowinput && parent->items.inrange(parent->menusel) && parent->items[parent->menusel]==this; } // text item @@ -257,10 +259,9 @@ struct mitemtextinput : mitemtext } } - virtual bool key(int code, bool isdown, int unicode) + virtual void key(int code, bool isdown, int unicode) { input.key(code, isdown, unicode); - return true; } virtual void init() @@ -337,11 +338,10 @@ struct mitemslider : mitem blendbox(x+tw+offset+FONTH, y, x+tw+offset+FONTH*1.2f, y+FONTH, false, -1, &white2); } - virtual bool key(int code, bool isdown, int unicode) + virtual void key(int code, bool isdown, int unicode) { if(code == SDLK_LEFT) slide(false); else if(code == SDLK_RIGHT) slide(true); - return true; } virtual void init() @@ -372,6 +372,46 @@ struct mitemslider : mitem } }; +// key input item + +struct mitemkeyinput : mitem +{ + char *text, *bindcmd, *keyname; + bool capture; + + mitemkeyinput(gmenu *parent, char *text, char *bindcmd, color *bgcolor) : mitem(parent, bgcolor), text(text), bindcmd(bindcmd), keyname(NULL), capture(false) {}; + + virtual int width() { return text_width(text)+(keyname ? text_width(keyname) : char_width('_')); } + + virtual void render(int x, int y, int w) + { + int tw = text_width(text), tk = (keyname ? text_width(keyname) : char_width('_')); + static color capturec(0.4f, 0, 0); + if(isselection()) blendbox(x+w-tk-FONTH, y-FONTH/6, x+w+FONTH, y+FONTH+FONTH/6, false, -1, capture ? &capturec : NULL); + draw_text(text, x, y); + draw_text(keyname ? keyname : "?", x+w-tk, y); + } + + virtual void init() { displaycurrentbind(); capture = false; } + + virtual void select() { capture = true; } + + virtual void key(int c, bool isdown, int unicode) + { + if(!capture) return; + keym *km; + while((km = findbinda(bindcmd))) { bindkey(km, ""); } // clear existing binds to this cmd + if(bindc(c, bindcmd)) parent->init(); // re-init all bindings + else conoutf("\f3could not bind key"); + } + + void displaycurrentbind() + { + keym *km = findbinda(bindcmd); + if(km) keyname = km->name; + } +}; + // console iface void *addmenu(const char *name, const char *title, bool allowinput, void (__cdecl *refreshfunc)(void *, bool)) @@ -428,6 +468,12 @@ void menuitemslider(char *text, char *min_, char *max_, char *value, char *step, lastmenu->items.add(new mitemslider(lastmenu, newstring(text), atoi(min_), atoi(max_), atoi(step), value[0] ? newstring(value) : NULL, display[0] ? newstring(display) : NULL, action[0] ? newstring(action) : NULL, NULL)); } +void menuitemkeyinput(char *text, char *bindcmd) +{ + if(!lastmenu) return; + lastmenu->items.add(new mitemkeyinput(lastmenu, newstring(text), newstring(bindcmd), NULL)); +} + void menumdl(char *mdl, char *anim, char *rotspeed, char *scale) { if(!lastmenu || !mdl || !anim) return; @@ -452,6 +498,7 @@ void chmenumdl(char *menu, char *mdl, char *anim, char *rotspeed, char *scale) COMMAND(menuitem, ARG_3STR); COMMAND(menuitemtextinput, ARG_4STR); COMMAND(menuitemslider, ARG_7STR); +COMMAND(menuitemkeyinput, ARG_4STR); COMMAND(showmenu, ARG_1STR); COMMAND(newmenu, ARG_1STR); COMMAND(menumdl, ARG_5STR); @@ -489,7 +536,8 @@ bool menukey(int code, bool isdown, int unicode) { if(!curmenu->allowinput) return false; mitem &m = *curmenu->items[menusel]; - return m.key(code, isdown, unicode); + m.key(code, isdown, unicode); + return true; } } diff --git a/source/src/protos.h b/source/src/protos.h index b43e2aa2..7bb1700a 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -49,6 +49,18 @@ extern void writebinds(FILE *f); extern void pasteconsole(char *dst); extern void conoutf(const char *s, ...); +struct keym +{ + int code; + char *name, *action; + + ~keym() { DELETEA(name); DELETEA(action); } +}; + +extern bool bindkey(keym *km, char *action); +extern keym *findbinda(char *action); +extern bool bindc(int code, char *action); + // menus extern void rendermenu(); extern bool menuvisible(); @@ -71,10 +83,10 @@ struct mitem virtual void render(int x, int y, int w); virtual int width() = 0; - virtual void select(){}; - virtual void focus(bool on) {}; - virtual bool key(int code, bool isdown, int unicode) { return false; } - virtual void init(){}; + virtual void select(){} + virtual void focus(bool on) {} + virtual void key(int code, bool isdown, int unicode) {} + virtual void init(){} bool isselection(); void renderbg(int x, int y, int w); }; @@ -96,6 +108,7 @@ struct gmenu void refresh(); void open(); void close(); + void init(); }; // serverbrowser diff --git a/source/src/scoreboard.cpp b/source/src/scoreboard.cpp index d79413d4..0fc26bd7 100644 --- a/source/src/scoreboard.cpp +++ b/source/src/scoreboard.cpp @@ -64,6 +64,7 @@ void renderscore(void *menu, playerent *d) const char *status = ""; if(d->clientrole==CR_MASTER) status = "\f0"; else if(d->clientrole==CR_ADMIN) status = "\f3"; + else if(d==player1) status = "\f1"; else if(d->state==CS_DEAD) status = "\f4"; s_sprintfd(lag)("%d", d->plag); sline &line = scorelines.add();