Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/input.cc')
-rw-r--r--src/client/input.cc542
1 files changed, 381 insertions, 161 deletions
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);