/* client/input.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 "core/core.h" #include "client/client.h" #include "client/input.h" #include "client/chat.h" #include "client/console.h" #include "client/keyboard.h" #include "client/video.h" #include "render/camera.h" #include "math/functions.h" #include "render/text.h" #include "SDL/SDL.h" namespace client { core::Cvar *cl_mousecontrol = 0; namespace input { // local controls float local_direction = 0.0f; float local_pitch = 0.0f; float local_thrust = 0.0f; float local_roll = 0.0f; // last controlled entity unsigned int last_control = 0; // mouse cursor position int mouse_x = 0; int mouse_y = 0; float mouse_pitch = 0; float mouse_direction = 0; // true if the mouse is in the deadzone bool mouse_deadzone = false; const float thruster_offset = 0.05f; void init() { con_print << "^BInitializing input..." << std::endl; 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"); } void shutdown() { con_print << "^BShutting down input..." << std::endl; // SDL_EnableUNICODE(0); } // handle key release for the game world void keyreleased(const SDL_keysym &keysym) { 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; case SDLK_SPACE: render::Camera::next_mode(); local_roll = 0; local_pitch = 0; local_direction = 0; break; case SDLK_KP8: // turn down local_pitch = 0.0f; break; case SDLK_KP2: // turn up local_pitch = 0.0f; break; case SDLK_KP4: // turn left local_direction = 0.0f; break; case SDLK_KP6: // turn right local_direction = 0.0f; break; case SDLK_KP_DIVIDE: // roll left local_roll = 0.0f; break; case SDLK_KP_MULTIPLY: // roll right local_roll = 0.0f; break; default: break; } } // handle key press events for the game world // http://docs.mandragor.org/files/Common_libs_documentation/SDL/SDL_Documentation_project_en/sdlkey.html void keypressed(const SDL_keysym &keysym) { 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; case SDLK_KP_DIVIDE: // roll left local_roll = 1.0f; break; case SDLK_KP_MULTIPLY: // roll light local_roll = -1.0f; break; default: break; } } // handle mouse button events for the game world // 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; } } void frame(float seconds) { if (core::localcontrol() && (last_control != core::localcontrol()->id())) { local_direction = 0.0f; local_pitch = 0.0f; local_roll = 0.0f; local_thrust = core::localcontrol()->thrust(); last_control = core::localcontrol()->id(); mouse_pitch = 0.0f; mouse_direction = 0.0f; mouse_x = video::width / 2; mouse_y = video::height / 2; render::Camera::reset(); } SDL_Event event; while (SDL_PollEvent(&event)) { 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); break; case SDL_KEYUP: if (event.key.keysym.sym == SDLK_PRINT) { video::screenshot(); } else if (!chat::visible() && !console()->visible() && core::application()->connected() && core::localcontrol()) // send key events to the game world keyreleased(event.key.keysym); 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; 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)); } else if (chat::visible()) { if(event.key.keysym.sym == SDLK_ESCAPE) { chat::toggle(); } else { // send key events to the chatbox chat::keypressed(translate_keysym(event.key.keysym)); } } 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); } } break; case SDL_QUIT: core::application()->shutdown(); break; } } if (!console()->visible() && core::application()->connected() && core::localcontrol()) { if (cl_mousecontrol->value()) { // the mouse will not react if it is in the deadzone int deadzone_size = 24; mouse_deadzone = true; // direction int l = mouse_x - (video::width >> 1); if (abs(l) < ( deadzone_size >> 1 )) { // dead zone mouse_direction = 0; } else { l = (mouse_x - deadzone_size) - ((video::width - deadzone_size) >> 1); mouse_direction = float (-l) / (float) ((video::width - deadzone_size) >> 1); mouse_deadzone = false; } // pitch int h = mouse_y - (video::height >> 1); if (abs(h) < ( deadzone_size >> 1 )) { // dead zone mouse_pitch = 0; } else { h = (mouse_y - deadzone_size) - ((video::height - deadzone_size) >> 1); mouse_pitch = float (-h) / (float) ((video::height - deadzone_size) >> 1); mouse_deadzone = false; } 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)); render::Camera::set_pitch(-mouse_pitch * math::absf(mouse_pitch)); } } else { 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); core::localcontrol()->set_thrust(local_thrust); core::localcontrol()->set_direction(local_direction); core::localcontrol()->set_pitch(local_pitch / render::Camera::aspect() ); core::localcontrol()->set_roll(local_roll); } } } // namespace input } // namespace client