From 9adc3720cd8fe2ba843d014dbbfe81bf936f9715 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Tue, 22 Jul 2008 17:21:35 +0000 Subject: more keyboard handling cleanups --- doc/TODO | 74 ++++++++++++------ src/client/action.cc | 30 ++++++++ src/client/action.h | 45 +++++++++++ src/client/input.cc | 198 +++++++++++++++++++------------------------------ src/client/key.cc | 6 +- src/client/key.h | 10 ++- src/client/keyboard.cc | 66 ++++++++--------- src/client/keyboard.h | 2 +- 8 files changed, 247 insertions(+), 184 deletions(-) create mode 100644 src/client/action.cc create mode 100644 src/client/action.h diff --git a/doc/TODO b/doc/TODO index 7663087..2dcf176 100644 --- a/doc/TODO +++ b/doc/TODO @@ -1,31 +1,43 @@ TODO milestone 1: - console text color and wrapping (ok) - keyboard binds (ok) - fix turning fix camera rotation fix camera frustum clip - - better crosshair bitmaps + fix cl_prediction milestone 2: targetting system server-client event system, hit-once lightweight entities explosion events weapon fire events + zones + +milestone 3: + gui filesystem: write a filesystem based on streams write handlers for zip - + fs_homedir, to define the writeable directory + fs_datadir, readonly package datadir + fs_base, fs_mod, fs_game, to be used by modules + model: engine flare key (ok) + split map loader from model (ok) + load vertices into VertexData support map classes (e.g. func_rotate), requires class VertexData - split map loader from model, load vertices into VertexData + rework textures/shaders + on .map load, convert 'common/entity' to a flag + rename 'entity' to 'primairy' + add 'common/primairy_dark', ''common/secondairy', 'common/secondairy_dark' and convert to flags + sort triangles by flags + render by flag + use quads array and quad flag? + core: connection to remote game (ok) read/write configuration file (ok) @@ -36,32 +48,38 @@ core: refactor 'say', it should not be a game function (ok) execute config files (ok) - zones - game module loading/unloading + zones (breaks network proto) + game module loading/unloading (breaks network proto, server must send module type) + support entity secondairy color (breaks network proto) + + toggle func to toggle a bool cvar network: UDP datagrams (ok) buffered sends (ok) client connection state (ok) zlib compression (partial) - fix lag (usable for now) + protocol version in handshake (ok) + rcon framework (ok) - protocol description - chat, channels - rcon, commands + protocol description (incomplete) + private chat + zone/system chat (requires zones) + group/clan chat (requires groups) + rcon authentication, rcon command, servers must be able to disable rcon - protocol version in handshake + fix lag/client prediction detect and disconnect clients behaving badly client: - input handler switching (ok) console chars (ok) - key bindings (ok) + console text color and wrapping (ok) + input handler switching (ok) + key binds (ok) + better crosshair bitmaps (ok) - keyboard handler, must be able to handle keyboard layouts - decent input handling implementation - - on-the-fly cl_mousecontrol (toggle function) + modifier key binds + keyboard repeat render: render pipeline (ok) @@ -70,13 +88,25 @@ render: texture registry (ok) add small camera light (ok) - text quads render pipe - fix lighting without sun + text quads render pipe? (see model quads) + test/fix? lighting without sun in world.ini + sun light strenght + +gui: + a gui library with widgets and buttons + convert console and chat to gui sound: engine sounds (ok) user interface sounds (ok) + enitity/event positional sounds + +game: + implement player credits + entity health/shield/armor + gui concept artwork + win32 port: network not functional (ok) texture loading is broken (ok) diff --git a/src/client/action.cc b/src/client/action.cc new file mode 100644 index 0000000..b86476e --- /dev/null +++ b/src/client/action.cc @@ -0,0 +1,30 @@ +/* + client/action.h + This file is part of the Osirion project and is distributed under + the terms and conditions of the GNU General Public License version 2 +*/ + +#include "client/action.h" + +namespace client +{ + +Action::Action(const char *name, Identifier action, const char *info) +{ + action_name.assign(name); + action_id = action; + + set_info(info); +} + +Action::~Action() +{ +} + +void Action::set_info(const char *info) { + if (info) + action_info.assign(info); + else + action_info.clear(); +} +} diff --git a/src/client/action.h b/src/client/action.h new file mode 100644 index 0000000..c7086c8 --- /dev/null +++ b/src/client/action.h @@ -0,0 +1,45 @@ +/* + client/action.h + This file is part of the Osirion project and is distributed under + the terms and conditions of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_CLIENT_ACTION_H__ +#define __INCLUDED_CLIENT_ACTION_H__ + +#include + +namespace client { + +/// an Action that can be bound to a key +class Action +{ +public: + /// actions + enum Identifier {None=0}; + + /// define a new action + Action(const char *name, Identifier action, const char *info = 0); + ~Action(); + + /// name of the Action + inline std::string const & name() const { return action_name; } + + /// Action Identifier + inline Identifier id() const { return action_id; } + + inline std::string const & info() const { return action_info; } + + /// set info + void set_info(const char *info); + + +private: + std::string action_name; + std::string action_info; + Identifier action_id; +}; + +} // namespace client + +#endif // __INCLUDED_CLIENT_ACTION_H__ diff --git a/src/client/input.cc b/src/client/input.cc index 775f03a..f8d76f2 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -29,9 +29,10 @@ namespace input //--- local variables --------------------------------------------- +// keyboard instance Keyboard *keyboard = 0; - -//bool free_control = true; +// keyboard modifiers shift, ctrl, alt etc +int keyboard_modifiers = 0; // local controls @@ -377,6 +378,73 @@ void action_release(std::string const &action) } } +void key_pressed(Key *key) +{ + + if ((key->sym() == SDLK_ESCAPE) || (key->bind(Key::None).compare("ui_console") == 0)) { + console()->toggle(); + local_direction = 0.0f; + local_pitch = 0.0f; + local_roll = 0.0f; + + render::Camera::set_direction(0.0f); + render::Camera::set_pitch(0.0f); + + } else if (console()->visible()) { + // send key events to the console + if (key->sym() < 512) + console()->keypressed(translate_keysym(key->sym(), keyboard_modifiers)); + + } else if (chat::visible()) { + // send key events to the chat box + if (key->sym() < 512) + chat::keypressed(translate_keysym(key->sym(), keyboard_modifiers)); + + } else if (core::application()->connected() && core::localcontrol()) { + + if ((key->sym() == 512 + SDL_BUTTON_LEFT) && targets::hover()) { + // hovering target selected + targets::select_target(targets::hover()); + + } else { + // FIXME modifiers + char c = key->bind(Key::None).c_str()[0]; + if (c == '+') { + // action bind + action_press(key->bind(Key::None)); + + } else if (c) { + // normal bind + core::cmd() << key->bind(Key::None) << "\n"; + } + } + + } else if (core::application()->connected()) { + // FIXME modifiers + + char c = key->bind(Key::None).c_str()[0]; + if (c && c != '+') { + // normal bind + core::cmd() << key->bind(Key::None) << "\n"; + } + } + +} + +void key_released(Key *key) +{ + if (core::application()->connected() && core::localcontrol() && !console()->visible() && !chat::visible()) { + + // FIXME modifiers + char c = key->bind(Key::None).c_str()[0]; + if (c == '+') { + // action bind + action_release(key->bind(Key::None)); + } + } +} + + void frame(float seconds) { if (core::localcontrol() && (last_control != core::localcontrol()->id())) { @@ -423,11 +491,13 @@ void frame(float seconds) break; case SDL_KEYDOWN: + keyboard_modifiers = event.key.keysym.mod; key = keyboard->press(event.key.keysym.sym); pressed = true; break; case SDL_KEYUP: + keyboard_modifiers = event.key.keysym.mod; key = keyboard->release(event.key.keysym.sym); pressed = false; break; @@ -439,74 +509,10 @@ void frame(float seconds) } if (key) { - if (pressed) { -/* - if (keysym.mod & KMOD_NUM) numlock = true else numlock = false; - if (keysym.mod & KMOD_CAPS) capslock = true; else capslock = false; - if ((keysym.mod & KMOD_LSHIFT) || (keysym.mod & KMOD_RSHIFT)) capslock != capslock; -*/ - // FIXME console key is always captured - // FIXME ESC should escape to gui - - if ((key->sym() == SDLK_ESCAPE) || (key->bind(Key::None).compare("ui_console") == 0)) { - console()->toggle(); - local_direction = 0.0f; - local_pitch = 0.0f; - local_roll = 0.0f; - - render::Camera::set_direction(0.0f); - render::Camera::set_pitch(0.0f); - - } else if (console()->visible()) { - // send key events to the console - if (event.type == SDL_KEYDOWN) - console()->keypressed(translate_keysym(event.key.keysym)); - - } else if (chat::visible()) { - // send key events to the chat box - if (event.type == SDL_KEYDOWN) - chat::keypressed(translate_keysym(event.key.keysym)); - - } else if (core::application()->connected() && core::localcontrol()) { - - if ((key->sym() == 512 + SDL_BUTTON_LEFT) && targets::hover()) { - // hovering target selected - targets::select_target(targets::hover()); - - } else { - // FIXME modifier - char c = key->bind(Key::None).c_str()[0]; - if (c == '+') { - // action bind - action_press(key->bind(Key::None)); - - } else if (c) { - // normal bind - core::cmd() << key->bind(Key::None) << "\n"; - } - } - - } else if (core::application()->connected()) { - // FIXME modifier - - char c = key->bind(Key::None).c_str()[0]; - if (c && c != '+') { - // normal bind - core::cmd() << key->bind(Key::None) << "\n"; - } - } - - } else { - - if (core::application()->connected() && core::localcontrol() && !console()->visible() && !chat::visible()) { - // FIXME modifier (note: mmmmm, modifier could be released by now) - char c = key->bind(Key::None).c_str()[0]; - if (c == '+') { - // action bind - action_release(key->bind(Key::None)); - } - } - } + if (pressed) + key_pressed(key); + else + key_released(key); } } @@ -555,58 +561,6 @@ void frame(float seconds) render::Camera::set_direction( -mouse_direction * math::absf(mouse_direction)); render::Camera::set_pitch(-mouse_pitch * math::absf(mouse_pitch)); } - - } else { - /* - const float MIN_DELTA = 10e-10; - const float ANGLE_DELTA = 0.01f; - - math::Axis target_axis; // FIXME - float cosangle; - const math::Axis & entity_axis= core::localcontrol()->axis(); - - // auto-level: pitch - local_pitch = 0; - - // project target_axis.up() into the plane with axis->left() normal - math::Vector3f n = entity_axis.left(); - math::Vector3f p = target_axis.up(); - float u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); - p = target_axis.up() + u * n; - - float side = entity_axis.forward().x * p.x + - entity_axis.forward().y * p.y + - entity_axis.forward().z * p.z; - - if ((fabs(side) - MIN_DELTA > 0)) { - - cosangle = math::dotproduct(p, entity_axis.up()); - if (fabs(cosangle) + ANGLE_DELTA < 1 ) { - local_pitch = -3 * math::sgnf(side) * (1-cosangle); - } - } - - // auto-level: roll - local_roll = 0; - - // project target_axis.up() into the plane with axis.forward() normal - n = entity_axis.forward(); - p = target_axis.up(); - u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); - p = target_axis.up() + u * n; - - side = entity_axis.left().x * p.x + - entity_axis.left().y * p.y + - entity_axis.left().z * p.z; - - if ((fabs(side) - MIN_DELTA > 0)) { - - cosangle = math::dotproduct(p, entity_axis.up()); - if (fabs(cosangle) + ANGLE_DELTA < 1 ) { - local_roll = 3 * math::sgnf(side) * (1-cosangle); - } - } - */ } diff --git a/src/client/key.cc b/src/client/key.cc index 9b0c942..27ed22a 100644 --- a/src/client/key.cc +++ b/src/client/key.cc @@ -9,7 +9,7 @@ namespace client { -Key::Key(const char *name, unsigned int keysym, char ascii, const char *bind) +Key::Key(const char *name, int keysym, char ascii, const char *bind) { key_sym = keysym; key_ascii = ascii; @@ -21,6 +21,10 @@ Key::Key(const char *name, unsigned int keysym, char ascii, const char *bind) if (bind) key_bind.assign(bind); + + key_bind_shift.clear(); + key_bind_ctrl.clear(); + key_bind_alt.clear(); } Key::~Key() diff --git a/src/client/key.h b/src/client/key.h index bd6f6bd..6f190c0 100644 --- a/src/client/key.h +++ b/src/client/key.h @@ -7,6 +7,8 @@ #ifndef __INCLUDED_CLIENT_KEY_H__ #define __INCLUDED_CLIENT_KEY_H__ +#include "SDL/SDL.h" + #include namespace client { @@ -20,11 +22,11 @@ class Key { public: /// define a new key - Key(const char *name, unsigned int keysym, char ascii=0, const char *bind=0); + Key(const char *name, int keysym, char ascii=0, const char *bind=0); ~Key(); /// key modifiers - enum Modifier { None=0, Shift=1, Ctrl=2, Alt=3 }; + enum Modifier { None=0, Shift=KMOD_LSHIFT+KMOD_RSHIFT, Ctrl=KMOD_LCTRL + KMOD_RCTRL, Alt=KMOD_LALT+KMOD_RALT }; /// clear all binds void clear(); @@ -44,11 +46,11 @@ public: inline char ascii() const { return key_ascii; } - inline unsigned int sym() const { return key_sym; } + inline int sym() const { return key_sym; } private: std::string key_name; - unsigned int key_sym; + int key_sym; char key_ascii; float key_pressed; diff --git a/src/client/keyboard.cc b/src/client/keyboard.cc index da93814..410e76c 100644 --- a/src/client/keyboard.cc +++ b/src/client/keyboard.cc @@ -429,17 +429,16 @@ void setkeyboardmode(bool input) */ } -unsigned int translate_keysym(const SDL_keysym &keysym) +unsigned int translate_keysym(int keysym, int modifier) { - int key = keysym.sym; bool shift = false; bool numlock = false; // keypad keys - if (keysym.mod & KMOD_NUM) { + if (modifier & KMOD_NUM) { numlock = true; - switch (key) { + switch (keysym) { case SDLK_KP0: return '0'; break; @@ -475,7 +474,7 @@ unsigned int translate_keysym(const SDL_keysym &keysym) break; } } else { - switch (key) { + switch (keysym) { case SDLK_KP0: return SDLK_INSERT; break; @@ -510,7 +509,7 @@ unsigned int translate_keysym(const SDL_keysym &keysym) } // special keys - switch (key) { + switch (keysym) { case SDLK_ESCAPE: return SDLK_ESCAPE; break; @@ -535,91 +534,90 @@ unsigned int translate_keysym(const SDL_keysym &keysym) } // caps lock - if (keysym.mod & KMOD_CAPS) + if (modifier & KMOD_CAPS) shift = true; // left/right shift - if ((keysym.mod & KMOD_LSHIFT) || (keysym.mod & KMOD_RSHIFT)) { + if ((KMOD_LSHIFT + KMOD_RSHIFT) & modifier) { shift = !shift; } if (shift) { - if ((key >= 'a' && key <= 'z')) { - key = key + 'A' - 'a'; - return key; + if ((keysym >= 'a' && keysym <= 'z')) { + return keysym + 'A' - 'a'; } - switch (key) { + switch (keysym) { case '`': - key = '~'; + return '~'; break; case '1': - key = '!'; + return '!'; break; case '2': - key = '@'; + return '@'; break; case '3': - key = '#'; + return '#'; break; case '4': - key = '$'; + return '$'; break; case '5': - key = '%'; + return '%'; break; case '6': - key = '^'; + return '^'; break; case '7': - key = '&'; + return '&'; break; case '8': - key = '*'; + return '*'; break; case '9': - key = '('; + return '('; break; case '0': - key = ')'; + return ')'; break; case '-': - key = '_'; + return '_'; break; case '=': - key = '+'; + return '+'; break; // second row case '[': - key = '{'; + return '{'; break; case ']': - key = '}'; + return '}'; break; case '|': - key = '\\'; + return '\\'; break; // third row case ';': - key = ':'; + return ':'; break; case '\'': - key = '"'; + return '"'; break; // fourth row case ',': - key = '<'; + return '<'; break; case '.': - key = '>'; + return '>'; break; case '/': - key = '?'; + return '?'; break; } } - return key; + return keysym; } } // namespace client diff --git a/src/client/keyboard.h b/src/client/keyboard.h index 1c70179..9712009 100644 --- a/src/client/keyboard.h +++ b/src/client/keyboard.h @@ -82,7 +82,7 @@ private: }; /// convert SDL_keysym to a keystroke -unsigned int translate_keysym(const SDL_keysym &keysym); +unsigned int translate_keysym(int keysym, int modifier); /// set the keyboard input mode /** @param input true for console input, false for game input -- cgit v1.2.3