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/input.cc | 542 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 381 insertions(+), 161 deletions(-) (limited to 'src/client/input.cc') 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); -- cgit v1.2.3