From 8c17868585e2a12f947ec387947c4521ef21d775 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Mon, 2 Jun 2008 16:20:47 +0000 Subject: keyboard binds --- src/client/Makefile.am | 8 +- src/client/chat.cc | 31 +-- src/client/chat.h | 2 +- src/client/client.cc | 2 +- src/client/console.cc | 35 +--- src/client/console.h | 2 +- src/client/input.cc | 542 ++++++++++++++++++++++++++++++++++--------------- src/client/input.h | 4 +- src/client/key.cc | 29 +++ src/client/key.h | 42 ++++ src/client/keyboard.cc | 334 +++++++++++++++++++++++++++++- src/client/keyboard.h | 66 +++++- src/client/view.cc | 31 ++- 13 files changed, 890 insertions(+), 238 deletions(-) create mode 100644 src/client/key.cc create mode 100644 src/client/key.h (limited to 'src/client') diff --git a/src/client/Makefile.am b/src/client/Makefile.am index 8c35895..56a2cc2 100644 --- a/src/client/Makefile.am +++ b/src/client/Makefile.am @@ -1,12 +1,12 @@ METASOURCES = AUTO INCLUDES = -I$(top_srcdir)/src -libclient_la_SOURCES = chat.cc client.cc console.cc hud.cc input.cc keyboard.cc \ - radar.cc video.cc view.cc +libclient_la_SOURCES = chat.cc client.cc console.cc hud.cc input.cc key.cc \ + keyboard.cc radar.cc video.cc view.cc libclient_la_CFLAGS = $(LIBSDL_CFLAGS) $(GL_CFLAGS) libclient_la_LDFLAGS = -avoid-version -no-undefined $(GL_LIBS) $(LIBSDL_LIBS) noinst_LTLIBRARIES = libclient.la -noinst_HEADERS = chat.h client.h console.h input.h keyboard.h radar.h video.h \ - view.h +noinst_HEADERS = chat.h client.h console.h input.h key.h keyboard.h radar.h \ + video.h view.h libclient_la_LIBADD = $(top_builddir)/src/render/librender.la \ $(top_builddir)/src/core/libcore.la diff --git a/src/client/chat.cc b/src/client/chat.cc index 6fd5008..6c3140d 100644 --- a/src/client/chat.cc +++ b/src/client/chat.cc @@ -24,46 +24,23 @@ size_t input_pos = 0; // chatbox visibility bool chat_visible = false; -//--- engine functions -------------------------------------------- - -void func_con_chat(std::string const &args) -{ - std::istringstream argstream(args); - int i; - - if (argstream >> i) { - if (i) chat_visible = true; else chat_visible = false; - } else - chat_visible = !chat_visible; - - -} - //--- public ------------------------------------------------------ void init() { // add engine functions - core::Func *func = core::Func::add("ui_chat", (core::FuncPtr) func_con_chat); - func->set_info("toggle chatbox"); - history.clear(); history.push_back(""); history_pos = history.rbegin(); input_pos = 0; - } void shutdown() { - // remove engine functions - core::Func::remove("ui_chat"); - history.clear(); input_pos = 0; } - bool visible() { return chat_visible; @@ -133,14 +110,18 @@ void toggle() (*history_pos).clear(); } - setkeyboardmode(chat_visible); + setkeyboardmode(console()->visible() || (core::application()->connected() && chat::visible())); } -void keypressed(int key) +void keypressed(unsigned int key) { std::deque::reverse_iterator upit; switch( key ) { + case SDLK_ESCAPE: + toggle(); + break; + case SDLK_TAB: core::CommandBuffer::complete( (*history_pos), input_pos); break; diff --git a/src/client/chat.h b/src/client/chat.h index 71fb9f5..fdf4c70 100644 --- a/src/client/chat.h +++ b/src/client/chat.h @@ -30,7 +30,7 @@ void draw(); void toggle(); /// handle keyboard input -void keypressed(int key); +void keypressed(unsigned int key); /// true of the console is visible bool visible(); diff --git a/src/client/client.cc b/src/client/client.cc index a3ad481..a3219e6 100644 --- a/src/client/client.cc +++ b/src/client/client.cc @@ -27,7 +27,7 @@ Client app; //--- engine functions -------------------------------------------- -void func_r_restart(std::stringstream &args) +void func_r_restart(std::string const &args) { video::shutdown(); diff --git a/src/client/console.cc b/src/client/console.cc index a09272a..c5feb86 100644 --- a/src/client/console.cc +++ b/src/client/console.cc @@ -4,18 +4,19 @@ the terms and conditions of the GNU General Public License version 2 */ -#include "client/console.h" +#include +#include +#include + #include "auxiliary/functions.h" +#include "client/chat.h" +#include "client/console.h" +#include "client/video.h" +#include "client/keyboard.h" #include "core/core.h" #include "filesystem/filesystem.h" #include "render/render.h" #include "render/textures.h" -#include "client/video.h" -#include "client/keyboard.h" - -#include -#include -#include namespace client { @@ -25,22 +26,12 @@ Console *console() { return &client_console; } -//--- engine functions -------------------------------------------- - -void func_ui_console(std::string const &args) -{ - - console()->toggle(); -} - //--- public ------------------------------------------------------ void Console::init() { con_print << "^BInitializing console..." << std::endl; - core::Func *func = core::Func::add("ui_console", (core::FuncPtr) func_ui_console); - func->set_info("toggle console on or off"); console()->load_history(); } @@ -49,9 +40,6 @@ void Console::shutdown() con_print << "^BShutting down console..." << std::endl; console()->save_history(); - - // remove engine functions - core::Func::remove("ui_console"); } //--- Console ----------------------------------------------------- @@ -102,13 +90,12 @@ void Console::toggle() } else { SDL_WM_GrabInput(SDL_GRAB_ON); SDL_ShowCursor(SDL_DISABLE); - //clear_notify(); } - - setkeyboardmode(visible()); + + setkeyboardmode(console()->visible() || (core::application()->connected() && chat::visible())); } -void Console::keypressed(int key) +void Console::keypressed(unsigned int key) { std::deque::reverse_iterator upit; diff --git a/src/client/console.h b/src/client/console.h index 533a8be..05d62ad 100644 --- a/src/client/console.h +++ b/src/client/console.h @@ -33,7 +33,7 @@ public: void toggle(); /// handle keyboard input - void keypressed(int key); + void keypressed(unsigned int key); /// true of the console is visible inline bool visible() { return console_visible; } diff --git a/src/client/input.cc b/src/client/input.cc index f75cbb9..3d5b30c 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -20,11 +20,16 @@ namespace client { -core::Cvar *cl_mousecontrol = 0; - namespace input { +//--- local variables --------------------------------------------- + +Keyboard *keyboard = 0; + +bool free_control = true; +bool free_control_override = false; + // local controls float local_direction = 0.0f; float local_pitch = 0.0f; @@ -43,156 +48,270 @@ float mouse_direction = 0; // true if the mouse is in the deadzone bool mouse_deadzone = false; +// true if the mouse has control +bool mouse_control = false; const float thruster_offset = 0.05f; +//--- engine functions -------------------------------------------- + +void func_screenshot(std::string const & args) +{ + video::screenshot(); +} + +void func_ui_control(std::string const &args) +{ + free_control = !free_control; + if (!free_control) { + local_direction = 0.0f; + local_pitch = 0.0f; + local_roll = 0.0f; + + render::Camera::set_direction(0.0f); + render::Camera::set_pitch(0.0f); + } +} + +void func_ui_console(std::string const &args) +{ + console()->toggle(); +} + +void func_ui_chat(std::string const &args) +{ + if (core::application()->connected()) { + chat::toggle(); + } +} + +void func_ui_view(std::string const &args) +{ + if (core::application()->connected() && core::localcontrol()) { + render::Camera::next_mode(); + local_roll = 0; + local_pitch = 0; + local_direction = 0; + } +} + +void func_list_keys(std::string const &args) +{ + if (keyboard) + keyboard->list_keys(); +} + +void func_list_binds(std::string const &args) +{ + if (keyboard) + keyboard->list_binds(); +} + +void func_bind(std::string const &args) +{ + if (keyboard) { + std::stringstream argstr(args); + std::string keyname; + if (argstr >> keyname) { + if (args.size() > keyname.size()+1) { + keyboard->bind(keyname, args.substr(keyname.size()+1)); + return; + } + } + } + + core::Func *func = core::Func::find("bind"); + con_print << "bind " << func->info() << std::endl; +} + +void func_unbind(std::string const &args) +{ + if (keyboard) { + std::stringstream argstr(args); + std::string keyname; + if (argstr >> keyname) { + keyboard->unbind(keyname); + return; + } + } + + core::Func *func = core::Func::find("unbind"); + con_print << "unbind " << func->info() << std::endl; +} + +//--- input functions --------------------------------------------- + void init() { con_print << "^BInitializing input..." << std::endl; + + keyboard = new Keyboard(); + client::setkeyboardmode(false); + SDL_ShowCursor(SDL_DISABLE); SDL_WM_GrabInput(SDL_GRAB_ON); // SDL_EnableUNICODE(1); - cl_mousecontrol = core::Cvar::get("cl_mousecontrol", "0", core::Cvar::Archive); - cl_mousecontrol->set_info("[bool] mouse control"); + + core::Func *func = 0; + + func = core::Func::add("ui_console", func_ui_console); + func->set_info("toggle console on or off"); + + func = core::Func::add("ui_chat", func_ui_chat); + func->set_info("toggle chatbox on or of"); + + func = core::Func::add("ui_view", func_ui_view); + func->set_info("switch view mode"); + + func = core::Func::add("ui_control",func_ui_control); + func->set_info("toggle control on or off"); + + func = core::Func::add("list_keys", func_list_keys); + func->set_info("list keyboard key names"); + + func = core::Func::add("list_binds",func_list_binds); + func->set_info("list keyboard binds"); + + func = core::Func::add("bind", (core::FuncPtr) func_bind); + func->set_info("[key] [str] bind a command to a key"); + + func = core::Func::add("unbind", func_unbind); + func->set_info("[key] unbind a key"); + + func = core::Func::add("screenshot", func_screenshot); + func->set_info("make a screenshot"); + + keyboard->load_binds(); } void shutdown() { con_print << "^BShutting down input..." << std::endl; + + core::Func::remove("list_keys"); + core::Func::remove("list_binds"); + + core::Func::remove("bind"); + core::Func::remove("unbind"); + + core::Func::remove("screenshot"); + + core::Func::remove("ui_console"); + core::Func::remove("ui_control"); + core::Func::remove("ui_chat"); + core::Func::remove("ui_view"); + + keyboard->save_binds(); + delete keyboard; + keyboard = 0; + + SDL_ShowCursor(SDL_ENABLE); + SDL_WM_GrabInput(SDL_GRAB_OFF); // SDL_EnableUNICODE(0); + } -// handle key release for the game world -void keyreleased(const SDL_keysym &keysym) +void action_press(std::string const &action) { - switch (keysym.sym) { - case SDLK_LEFT: - render::Camera::set_direction(0.0f); - break; - case SDLK_RIGHT: - render::Camera::set_direction(0.0f); - break; - case SDLK_UP: - render::Camera::set_pitch(0.0f); - break; - case SDLK_DOWN: - render::Camera::set_pitch(0.0f); - break; + /* -- thruster ------------------------------------ */ + if (action.compare("+thrust") == 0) { + local_thrust += thruster_offset; - case SDLK_SPACE: - render::Camera::next_mode(); - local_roll = 0; - local_pitch = 0; - local_direction = 0; - break; + } else if (action.compare("-thrust") == 0) { + local_thrust -= 2.0f * thruster_offset; + + /* -- mouse control ------------------------------- */ + } else if (action.compare("+control") == 0) { + free_control_override = true; - case SDLK_KP8: // turn down - local_pitch = 0.0f; - break; + /* -- directional control ------------------------- */ + } else if (action.compare("+left") == 0) { + local_direction = 1.0f; - case SDLK_KP2: // turn up - local_pitch = 0.0f; - break; + } else if (action.compare("+right") == 0) { + local_direction = -1.0f; - case SDLK_KP4: // turn left - local_direction = 0.0f; - break; + } else if (action.compare("+up") == 0) { + local_pitch = 1.0f; - case SDLK_KP6: // turn right - local_direction = 0.0f; - break; + } else if (action.compare("+down") == 0) { + local_pitch = -1.0f; - case SDLK_KP_DIVIDE: // roll left - local_roll = 0.0f; - break; - - case SDLK_KP_MULTIPLY: // roll right - local_roll = 0.0f; - break; + } else if (action.compare("+rollleft") == 0) { + local_roll = 1.0f; - default: - break; - } -} + } else if (action.compare("+rollright") == 0) { + local_roll = -1.0f; + + /* -- camera control ------------------------------ */ + } else if (action.compare("+camleft") == 0) { + render::Camera::set_direction(1.0f); -// handle key press events for the game world + } else if (action.compare("+camright") == 0) { + render::Camera::set_direction(-1.0f); -// http://docs.mandragor.org/files/Common_libs_documentation/SDL/SDL_Documentation_project_en/sdlkey.html -void keypressed(const SDL_keysym &keysym) + } else if (action.compare("+camup") == 0) { + render::Camera::set_pitch(1.0f); + + } else if (action.compare("+camdown") == 0) { + render::Camera::set_pitch(-1.0f); + } else + con_warn << "Unknown action " << action << std::endl; +} + +void action_release(std::string const &action) { - switch (keysym.sym) { - case SDLK_LEFT: - render::Camera::set_direction(1.0f); - break; - case SDLK_RIGHT: - render::Camera::set_direction(-1.0f); - break; - case SDLK_UP: - render::Camera::set_pitch(1.0f); - break; - case SDLK_DOWN: - render::Camera::set_pitch(-1.0f); - break; - - case SDLK_KP_PLUS: - local_thrust += thruster_offset; - break; - - case SDLK_KP_MINUS: - local_thrust -= 2.0f * thruster_offset; - break; - - case SDLK_KP8: // down - local_pitch = -1.0f; - break; - - case SDLK_KP2: // up - local_pitch = 1.0f; - break; - - case SDLK_KP4: // left - local_direction = 1.0f; - break; - - case SDLK_KP6: // right - local_direction = -1.0f; - break; - - case SDLK_KP5: // level - local_direction = 0; - local_pitch = 0; - local_roll = 0; - break; + /* -- thruster ------------------------------------ */ + if (action.compare("+thrust") == 0) { + - case SDLK_KP_DIVIDE: // roll left - local_roll = 1.0f; - break; + } else if (action.compare("-thrust") == 0) { - case SDLK_KP_MULTIPLY: // roll light - local_roll = -1.0f; - break; + /* -- mouse control ------------------------------- */ + } else if (action.compare("+control") == 0) { + free_control_override = false; + if (!free_control) { + local_direction = 0.0f; + local_pitch = 0.0f; + local_roll = 0.0f; - default: - break; - } - -} + render::Camera::set_direction(0.0f); + render::Camera::set_pitch(0.0f); + } -// handle mouse button events for the game world + /* -- directional control ------------------------- */ + } else if (action.compare("+left") == 0) { + local_direction = 0.0f; -// http://docs.mandragor.org/files/Common_libs_documentation/SDL/SDL_Documentation_project_en/sdlmousebuttonevent.html -void mousebuttonpressed(const SDL_MouseButtonEvent &button) -{ - switch (button.button) { - case SDL_BUTTON_WHEELUP: - local_thrust += thruster_offset; - break; - - case SDL_BUTTON_WHEELDOWN: - local_thrust -= 2.0f * thruster_offset; - break; + } else if (action.compare("+right") == 0) { + local_direction = 0.0f; + + } else if (action.compare("+up") == 0) { + local_pitch = 0.0f; + + } else if (action.compare("+down") == 0) { + local_pitch = 0.0f; + + } else if (action.compare("+rollleft") == 0) { + local_roll = 0.0f; + + } else if (action.compare("+rollright") == 0) { + local_roll = 0.0f; + + /* -- camera control ------------------------------ */ + } else if (action.compare("+camleft") == 0) { + render::Camera::set_direction(0.0f); + + } else if (action.compare("+camright") == 0) { + render::Camera::set_direction(0.0f); + + } else if (action.compare("+camup") == 0) { + render::Camera::set_pitch(0.0f); + + } else if (action.compare("+camdown") == 0) { + render::Camera::set_pitch(0.0f); } } @@ -209,74 +328,125 @@ void frame(float seconds) mouse_x = video::width / 2; mouse_y = video::height / 2; render::Camera::reset(); + free_control = true; + free_control_override = false; } SDL_Event event; - + Key *key = 0; + bool pressed = false; + while (SDL_PollEvent(&event)) { - + pressed = false; + key = 0; + switch (event.type) { + case SDL_MOUSEMOTION: mouse_x = event.motion.x; mouse_y = event.motion.y; break; + case SDL_MOUSEBUTTONDOWN: - if (!console()->visible() && core::application()->connected() && core::localcontrol()) - mousebuttonpressed(event.button); + key = keyboard->press(512 + event.button.button); + pressed = true; + break; + case SDL_MOUSEBUTTONUP: + key = keyboard->release(512 + event.button.button); + pressed = false; + break; + + case SDL_KEYDOWN: + key = keyboard->press(event.key.keysym.sym); + pressed = true; break; + case SDL_KEYUP: - if (event.key.keysym.sym == SDLK_PRINT) { - video::screenshot(); - } else if (!chat::visible() && !console()->visible() && - core::application()->connected() && core::localcontrol()) + key = keyboard->release(event.key.keysym.sym); + pressed = false; + break; - // send key events to the game world - keyreleased(event.key.keysym); + case SDL_QUIT: + core::application()->shutdown(); + return; break; - case SDL_KEYDOWN: - if (chat::visible() && !console()->visible() && (event.key.keysym.sym == SDLK_ESCAPE)) { - chat::toggle(); - } else if (event.key.keysym.sym == '`' || event.key.keysym.sym == '~' || (event.key.keysym.sym == SDLK_ESCAPE)) { - //last_control = 0; + } + + 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 screenshot and console are always captured + if (key->bind().compare("ui_console") == 0) { console()->toggle(); - - /* - if (console()->visible() && chat::visible()) - chat::toggle(); - */ - } else if (console()->visible()) { - // send key events to the console - console()->keypressed(translate_keysym(event.key.keysym)); + 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 (key->bind().compare("screenshot") == 0) { + video::screenshot(); + + } else if (console()->visible()) { + // FIXME send key events to the console + if (event.type == SDL_KEYDOWN) + console()->keypressed(translate_keysym(event.key.keysym)); + } else if (chat::visible()) { - if(event.key.keysym.sym == SDLK_ESCAPE) { - chat::toggle(); - } else { - // send key events to the chatbox + // FIXME 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()) { + + char c = key->bind().c_str()[0]; + if (c == '+' || c == '-') { + // action bind + action_press(key->bind()); + + } else if (c) { + // normal bind + core::cmd() << key->bind() << "\n"; } - } else if(core::application()->connected()) { - if ((event.key.keysym.sym == 't') || (event.key.keysym.sym == 'T')) { - chat::toggle(); - } else if (core::localcontrol()) { - // send key events to the game world - keypressed(event.key.keysym); + } else if (core::application()->connected()) { + + char c = key->bind().c_str()[0]; + if (c && c != '+' && c != '-') { + // normal bind + core::cmd() << key->bind() << "\n"; } } - break; - case SDL_QUIT: - core::application()->shutdown(); - break; + + } else { + + if (core::application()->connected() && core::localcontrol()) { + + char c = key->bind().c_str()[0]; + if (c == '+' || c == '-') { + // action bind + action_release(key->bind()); + } + } + } } - } + + mouse_control = false; + mouse_deadzone = false; - if (!console()->visible() && core::application()->connected() && core::localcontrol()) { - - if (cl_mousecontrol->value()) { + if (core::application()->connected() && core::localcontrol()) { + + mouse_control = !console()->visible() && (free_control || free_control_override); + + if (mouse_control) { // the mouse will not react if it is in the deadzone - int deadzone_size = 24; + int deadzone_size = 8; mouse_deadzone = true; // direction @@ -306,6 +476,7 @@ void frame(float seconds) if ((render::Camera::mode() == render::Camera::Track) || (render::Camera::mode() == render::Camera::Cockpit)) { local_direction = mouse_direction * math::absf(mouse_direction); local_pitch = mouse_pitch * math::absf(mouse_pitch); + } else if (render::Camera::mode() == render::Camera::Free) { // squared values to smoothen camera movement render::Camera::set_direction( -mouse_direction * math::absf(mouse_direction)); @@ -313,12 +484,61 @@ void frame(float seconds) } } 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; - math::clamp(local_direction, -1.0f, 1.0f); - math::clamp(local_pitch, -1.0f, 1.0f); + 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); + } + } + */ } + math::clamp(local_direction, -1.0f, 1.0f); + math::clamp(local_pitch, -1.0f, 1.0f); math::clamp(local_thrust, 0.0f, 1.0f); math::clamp(local_roll, -1.0f, 1.0f); diff --git a/src/client/input.h b/src/client/input.h index bcbba9b..87f7dfe 100644 --- a/src/client/input.h +++ b/src/client/input.h @@ -12,8 +12,6 @@ namespace client { -extern core::Cvar *cl_mousecontrol; - namespace input { @@ -28,7 +26,9 @@ void frame(float seconds); extern int mouse_x; extern int mouse_y; + extern bool mouse_deadzone; +extern bool mouse_control; } // namespace input diff --git a/src/client/key.cc b/src/client/key.cc new file mode 100644 index 0000000..066f6ef --- /dev/null +++ b/src/client/key.cc @@ -0,0 +1,29 @@ +/* + client/key.cc + 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/key.h" + +namespace client { + +Key::Key(const char *name, unsigned int keysym, char ascii, const char *bind) +{ + key_sym = keysym; + key_ascii = ascii; + key_pressed = 0; + + key_name.assign(name); + + if (bind) + key_bind.assign(bind); + else + key_bind.clear(); +} + +Key::~Key() +{ +} + +} diff --git a/src/client/key.h b/src/client/key.h new file mode 100644 index 0000000..ece7669 --- /dev/null +++ b/src/client/key.h @@ -0,0 +1,42 @@ +/* + client/key.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_KEY_H__ +#define __INCLUDED_CLIENT_KEY_H__ + +#include + +namespace client { + +class Key +{ +public: + Key(const char *name, unsigned int keysym, char ascii=0, const char *bind=0); + ~Key(); + + inline float & pressed() { return key_pressed; } + + inline std::string const & name() const { return key_name; } + + inline std::string & bind() { return key_bind; } + + inline char ascii() const { return key_ascii; } + + inline unsigned int sym() const { return key_sym; } + +private: + unsigned int key_sym; + char key_ascii; + + std::string key_name; + std::string key_bind; + + float key_pressed; +}; + +} // namespace client + +#endif // __INCLUDED_CLIENT_KEY_H__ diff --git a/src/client/keyboard.cc b/src/client/keyboard.cc index 8566ded..f9be4f5 100644 --- a/src/client/keyboard.cc +++ b/src/client/keyboard.cc @@ -4,21 +4,344 @@ the terms and conditions of the GNU General Public License version 2 */ -#include "client/keyboard.h" - #include +#include +#include + +#include "auxiliary/functions.h" +#include "client/keyboard.h" +#include "core/application.h" +#include "core/commandbuffer.h" +#include "filesystem/filesystem.h" +#include "sys/sys.h" namespace client { +/* +Notes: +http://docs.mandragor.org/files/Common_libs_documentation/SDL/SDL_Documentation_project_en/sdlkey.html +*/ + +Keyboard::Keyboard() +{ + numlock = false; + capslock = false; + + add_key("backspace", SDLK_BACKSPACE); + add_key("tab", SDLK_TAB); + add_key("clear", SDLK_CLEAR); + add_key("enter", SDLK_RETURN); + add_key("pause", SDLK_PAUSE); + add_key("escape", SDLK_ESCAPE); + add_key("space", SDLK_SPACE, ' ', "ui_control"); + add_key("!", SDLK_EXCLAIM, '!'); + add_key("\"", SDLK_QUOTEDBL, '"'); + add_key("#", SDLK_HASH, '#'); + add_key("$", SDLK_DOLLAR, '$'); + add_key("&", SDLK_AMPERSAND, '&'); + add_key("'", SDLK_QUOTE, '\''); + add_key("(", SDLK_LEFTPAREN, '('); + add_key(")", SDLK_RIGHTPAREN, ')'); + add_key("*", SDLK_ASTERISK, '*'); + add_key("+", SDLK_PLUS, '+'); + add_key(",", SDLK_COMMA, ','); + add_key("-", SDLK_MINUS, '-'); + add_key(".", SDLK_PERIOD, '.'); + add_key("/", SDLK_SLASH, '/'); + + add_key("0", SDLK_0, '0'); + add_key("1", SDLK_1, '1'); + add_key("2", SDLK_2, '2'); + add_key("3", SDLK_3, '3'); + add_key("4", SDLK_4, '4'); + add_key("5", SDLK_5, '5'); + add_key("6", SDLK_6, '6'); + add_key("7", SDLK_7, '7'); + add_key("8", SDLK_8, '8'); + add_key("9", SDLK_9, '9'); + + add_key(":", SDLK_COLON, ':'); + add_key(";", SDLK_SEMICOLON, ';'); + add_key("<", SDLK_LESS, '<'); + add_key("=", SDLK_EQUALS, '='); + add_key(">", SDLK_GREATER, '>'); + add_key("?", SDLK_QUESTION, '?'); + add_key("@", SDLK_AT, '@'); + add_key("[", SDLK_LEFTBRACKET, '['); + add_key("\\", SDLK_BACKSLASH, '\\'); + add_key("]", SDLK_RIGHTBRACKET, ']'); + add_key("^", SDLK_CARET, '^'); + add_key("_", SDLK_UNDERSCORE, '_'); + add_key("`", SDLK_BACKQUOTE, '`', "ui_console"); + + add_key("a", SDLK_a, 'a'); + add_key("b", SDLK_b, 'b'); + add_key("c", SDLK_c, 'c'); + add_key("d", SDLK_d, 'd'); + add_key("e", SDLK_e, 'e'); + add_key("f", SDLK_f, 'f'); + add_key("g", SDLK_g, 'g'); + add_key("h", SDLK_h, 'h'); + add_key("i", SDLK_i, 'i'); + add_key("j", SDLK_j, 'j'); + add_key("k", SDLK_k, 'k'); + add_key("l", SDLK_l, 'l'); + add_key("m", SDLK_m, 'm'); + add_key("n", SDLK_n, 'n'); + add_key("o", SDLK_o, 'o'); + add_key("p", SDLK_p, 'p'); + add_key("q", SDLK_q, 'q'); + add_key("r", SDLK_r, 'r'); + add_key("s", SDLK_s, 's'); + add_key("t", SDLK_t, 't', "ui_chat"); + add_key("u", SDLK_u, 'u'); + add_key("v", SDLK_v, 'v', "ui_view"); + add_key("w", SDLK_w, 'w'); + add_key("x", SDLK_x, 'x'); + add_key("y", SDLK_y, 'y'); + add_key("z", SDLK_z, 'z'); + + add_key("del", SDLK_DELETE); + add_key("kp0", SDLK_KP0); + add_key("kp1", SDLK_KP1); + add_key("kp2", SDLK_KP2, 0, "+down"); + add_key("kp3", SDLK_KP3); + add_key("kp4", SDLK_KP4, 0, "+left"); + add_key("kp5", SDLK_KP5); + add_key("kp6", SDLK_KP6, 0, "+right"); + add_key("kp7", SDLK_KP7); + add_key("kp8", SDLK_KP8, 0, "+up"); + add_key("kp9", SDLK_KP9); + + add_key("kpperiod", SDLK_KP_PERIOD, '.'); + add_key("kpdiv", SDLK_KP_DIVIDE, '/', "+rollleft"); + add_key("kpmul", SDLK_KP_MULTIPLY, '*', "+rollright"); + add_key("kpmin", SDLK_KP_MINUS, '-', "-thrust"); + add_key("kpplus", SDLK_KP_PLUS, '+', "+thrust"); + add_key("kpenter", SDLK_KP_ENTER, '\n'); + add_key("kpequal", SDLK_KP_EQUALS, '='); + + add_key("up", SDLK_UP, 0, "+camup"); + add_key("down", SDLK_DOWN, 0, "+camdown"); + add_key("right", SDLK_RIGHT, 0, "+camright"); + add_key("left", SDLK_LEFT, 0, "+camleft"); + + add_key("insert", SDLK_INSERT); + add_key("home", SDLK_HOME); + add_key("end", SDLK_END); + add_key("pageup", SDLK_PAGEUP); + add_key("pagedown", SDLK_PAGEDOWN); + + add_key("f1", SDLK_F1); + add_key("f2", SDLK_F2); + add_key("f3", SDLK_F3); + add_key("f4", SDLK_F4); + add_key("f5", SDLK_F5); + add_key("f6", SDLK_F6); + add_key("f7", SDLK_F7); + add_key("f8", SDLK_F8); + add_key("f9", SDLK_F9); + add_key("f10", SDLK_F11); + add_key("f11", SDLK_F11); + add_key("f12", SDLK_F12); + add_key("f13", SDLK_F13); + add_key("f14", SDLK_F14); + add_key("f15", SDLK_F15); + + add_key("numlock", SDLK_NUMLOCK); + add_key("capslock", SDLK_CAPSLOCK); + add_key("scrollock", SDLK_SCROLLOCK); + + add_key("rshift", SDLK_RSHIFT); + add_key("lshift", SDLK_LSHIFT); + + add_key("rctrl", SDLK_RCTRL); + add_key("lctrl", SDLK_LCTRL); + + add_key("ralt", SDLK_RALT); + add_key("lalt", SDLK_LALT); + + add_key("rmeta", SDLK_RMETA); + add_key("lmeta", SDLK_LMETA); + add_key("lwin", SDLK_LSUPER); + add_key("rwin", SDLK_RSUPER); + add_key("mode", SDLK_MODE); + + add_key("help", SDLK_HELP); + add_key("print", SDLK_PRINT, 0, "screenshot"); + add_key("sysrq", SDLK_SYSREQ); + add_key("breal", SDLK_BREAK); + add_key("menu", SDLK_MENU); + add_key("power", SDLK_POWER); + add_key("euro", SDLK_EURO); + + // mouse key aliases + add_key("lmb", 512 + SDL_BUTTON_LEFT, 0, "+control"); + add_key("rmb", 512 + SDL_BUTTON_RIGHT); + add_key("mmb", 512 + SDL_BUTTON_MIDDLE); + + add_key("mwup", 512 + SDL_BUTTON_WHEELUP, 0, "+thrust"); + add_key("mwdown", 512 + SDL_BUTTON_WHEELDOWN, 0, "-thrust"); +} + +Keyboard::~Keyboard() +{ + for(iterator it = begin(); it != end(); it++) + delete (*it).second; + + keys.clear(); +} + +void Keyboard::save_binds() +{ + std::string filename(filesystem::writedir); + filename.append("binds.cfg"); + std::ofstream ofs(filename.c_str()); + + if (!ofs.is_open()) { + con_warn << "Could not write " << filename << std::endl; + return; + } + + con_print << " writing keyboard binds to " << filename << std::endl; + + ofs << "# binds.cfg - osirion keyboard binds" << std::endl; + ofs << "# this file is automaticly generated" << std::endl; + + iterator it; + for (it = begin(); it != end(); it++) { + Key *key = (*it).second; + if (key->bind().size()) { + ofs << "bind " << key->name() << " " << key->bind() << std::endl; + } else { + ofs << "unbind " << key->name() << std::endl; + } + } + ofs.close(); +} + +void Keyboard::load_binds() +{ + std::string filename(filesystem::writedir); + filename.append("binds.cfg"); + std::ifstream ifs(filename.c_str(), std::ifstream::in); + + if (!ifs.is_open()) { + con_warn << "Could not read " << filename << std::endl; + return; + } + + con_print << " reading keyboard binds from " << filename << std::endl; + + char line[MAXCMDSIZE]; + while (ifs.getline(line, MAXCMDSIZE-1)) { + if (line[0] && line[0] != '#' && line[0] != ';') + core::cmd() << line << '\n'; + } + + // execute commands in the buffer + core::CommandBuffer::exec(); +} +Key * Keyboard::release(unsigned int sym) +{ + Key *key = find(sym); + if (!key) { + return 0; + } + + key->pressed() = 0; + return key; +} + +Key * Keyboard::press(unsigned int sym) +{ + Key *key = find(sym); + if (!key) { + return 0; + } + + if (!key->pressed()) + key->pressed() = core::application()->time(); + + return key; +} + +Key *Keyboard::find(std::string const & name) +{ + Key *key = 0; + for (iterator it = begin(); it != end() && !key; it++) { + if ((*it).second->name().compare(name) == 0) { + key = (*it).second; + } + } + return key; +} + +Key *Keyboard::find(unsigned int keysym) +{ + iterator it = keys.find(keysym); + if (it == end()) + return 0; + else + return (*it).second; +} + +void Keyboard::bind(std::string const &name, const std::string str) +{ + Key *key = find(name); + if (key) { + key->bind().assign(str); + aux::trim(key->bind()); + } else { + con_print << "Key '" << name << "' not found." << std::endl; + } +} + +void Keyboard::unbind(std::string const &name) +{ + Key *key = find(name); + if (key) { + key->bind().clear(); + } else { + con_print << "Key '" << name << "' not found." << std::endl; + } +} + +void Keyboard::add_key(const char *name, const unsigned int keysym, const char ascii, const char *bind) +{ + keys[keysym] = new Key(name, keysym, ascii, bind); +} + +void Keyboard::list_keys() +{ + for (iterator it = begin(); it != end(); it++) { + con_print << " " << aux::spaces((*it).second->name(), 6) << " " << (*it).second->bind() << std::endl; + } + con_print << keys.size() << " keys" << std::endl; +} + +void Keyboard::list_binds() +{ + size_t n =0; + for (iterator it = begin(); it != end(); it++) { + if ((*it).second->bind().size()) { + con_print << " " << aux::spaces((*it).second->name(), 6) << " " << (*it).second->bind() << std::endl; + n++; + } + } + con_print << n << " binds" << std::endl; +} + void setkeyboardmode(bool input) { - if(input) +/* if(input) SDL_EnableKeyRepeat(250, SDL_DEFAULT_REPEAT_INTERVAL); else SDL_EnableKeyRepeat(10, SDL_DEFAULT_REPEAT_INTERVAL); +*/ } -int translate_keysym(const SDL_keysym &keysym) +unsigned int translate_keysym(const SDL_keysym &keysym) { int key = keysym.sym; @@ -96,6 +419,9 @@ int translate_keysym(const SDL_keysym &keysym) // special keys switch(key) { + case SDLK_ESCAPE: + return SDLK_ESCAPE; + break; case SDLK_KP_ENTER: return SDLK_RETURN; break; diff --git a/src/client/keyboard.h b/src/client/keyboard.h index 6805818..fb9efaf 100644 --- a/src/client/keyboard.h +++ b/src/client/keyboard.h @@ -4,21 +4,77 @@ the terms and conditions of the GNU General Public License version 2 */ -#ifndef __INCLUDED_CLIENT_KEYS_H__ -#define __INCLUDED_CLIENT_KEYS_H__ +#ifndef __INCLUDED_CLIENT_KEYBOARD_H__ +#define __INCLUDED_CLIENT_KEYBOARD_H__ + +#include +#include #include "SDL/SDL.h" +#include "client/key.h" + namespace client { +class Keyboard +{ +public: + Keyboard(); + ~Keyboard(); + + /// find a key on a keysym + Key *find(unsigned int keysym); + + /// find a key on name + Key *find(std::string const & name); + + /// bind a string to a key + void bind(std::string const &name, const std::string str); + + /// clear the string bound to a key + void unbind(std::string const &name); + + /// list keyboard key names + void list_keys(); + + /// list keyboard binds + void list_binds(); + + /// load keyboard binds + void load_binds(); + + /// save keyboard binds + void save_binds(); + + /// a key has been pressed + Key *press(unsigned int sym); + + /// a key has been pressed + Key *release(unsigned int sym); + +private: + typedef std::map::iterator iterator; + + inline iterator begin() { return keys.begin(); } + + inline iterator end() { return keys.end(); } + + void add_key(const char *name, const unsigned int keysym, const char ascii=0, const char *bind=0); + + std::map keys; + + bool numlock; + bool capslock; +}; + /// convert SDL_keysym to a keystroke -int translate_keysym(const SDL_keysym &keysym); +unsigned int translate_keysym(const SDL_keysym &keysym); /// set the keyboard input mode /** @param input true for console input, false for game input */ void setkeyboardmode(bool input); -} // namespace client +} -#endif // __INCLUDED_CLIENT_KEYS_H__ +#endif // __INCLUDED_CLIENT_KEYBOARD_H__ diff --git a/src/client/view.cc b/src/client/view.cc index 6d3f456..d796655 100644 --- a/src/client/view.cc +++ b/src/client/view.cc @@ -190,21 +190,32 @@ void draw_cursor() float crosshair_size = 48.0f; float x = input::mouse_x - (crosshair_size /2); float y = input::mouse_y - (crosshair_size /2); -// 0 + using namespace render; - render::Textures::bind("bitmaps/crosshair"); + math::Color color; - if (cl_crosshaircolor && cl_crosshaircolor->value()) { - std::stringstream colorstr(cl_crosshaircolor->str()); - colorstr >> color; - } + color.a = 0.5f; - if (cl_mousecontrol->value() && input::mouse_deadzone) - color.a = 0.3f; - else - color.a = 0.5f; + if (render::Camera::mode() == render::Camera::Overview) { + render::Textures::bind("bitmaps/crosshairs/aim"); + + } else { + + if (input::mouse_control) { + render::Textures::bind("bitmaps/crosshairs/control"); + + if (cl_crosshaircolor && cl_crosshaircolor->value()) { + std::stringstream colorstr(cl_crosshaircolor->str()); + colorstr >> color; + } + } else { + + render::Textures::bind("bitmaps/crosshairs/aim"); + } + + } gl::color(color); gl::begin(gl::Quads); -- cgit v1.2.3