#include "ControllerBase.h" #include "ModelBase.h" #include "ViewBase.h" #include "CommandsGlobal.h" #include "keytable.h" namespace Engine { static ControllerBase *ControllerInstance = NULL; /* * Helper functions */ /** \brief Converts the SDL_BUTTON_* to a value we know */ MouseButton convert_sdl_button (Uint8 button) { MouseButton mouse_button; switch (button) { case SDL_BUTTON_LEFT: mouse_button = MouseButtonLeft; break; case SDL_BUTTON_MIDDLE: mouse_button = MouseButtonMiddle; break; case SDL_BUTTON_RIGHT: mouse_button = MouseButtonRight; break; case SDL_BUTTON_WHEELUP: mouse_button = MouseButtonWheelUp; break; case SDL_BUTTON_WHEELDOWN: mouse_button = MouseButtonWheelDown; break; default: mouse_button = MouseButtonUnknown; break; } return mouse_button; } /* * Inherited Module functions */ int ControllerBase::OnInit (int argc, char* argv[]) { LogDebug ("Controller Init"); // we want to use key repeat so that we can keep e.g. backspace pressed in a // LineEdit SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); // we also enable unicode processing all the time as it is only little // overhead and simplifies text input a lot SDL_EnableUNICODE(1); // clear all bindings int i; for (i = 0; i < BINDING_KEYS_LAST; i++) { mBindings[i] = ""; mButtonStates.set(i, false); } uistate.activeitem = 0; uistate.hotitem = 0; uistate.kbditem = 0; uistate.last_keysym = SDLK_CLEAR; uistate.last_unicode = 0; uistate.last_key = SDLK_CLEAR; uistate.lastwidget = 0; ControllerInstance = this; return 0; } void ControllerBase::OnDestroy () { ControllerInstance = NULL; LogDebug ("Controller Destroy"); } /* * Module specific functions */ bool ControllerBase::BindKey (int key, const char *command) { if (key <= 0 || key >= BINDING_KEYS_LAST) { LogError ("Could not bind to key with index '%d': invalid index!", key); return false; } mBindings[key] = command; return true; } void ControllerBase::Process () { ProcessEvents (); mView->CalcWorldCoordinates (mMouseScreenPosition[0], mMouseScreenPosition[1], 0., mMouseWorldPosition); /* LogMessage ("Screenpos = %2d,%2d Worldpos = %f,%f,%f", mMouseScreenPosition[0], mMouseScreenPosition[1], mMouseWorldPosition[0], mMouseWorldPosition[1], mMouseWorldPosition[2]); */ } void ControllerBase::ProcessEvents () { SDL_Event event; while (SDL_PollEvent(&event)) { /* We are only worried about SDL_KEYDOWN and SDL_KEYUP events */ switch (event.type) { case SDL_KEYDOWN: OnKeyDown (event.key.keysym); break; case SDL_KEYUP: OnKeyUp (event.key.keysym); break; case SDL_MOUSEMOTION: OnMouseMotion(event.motion.x, event.motion.y); break; case SDL_MOUSEBUTTONDOWN: OnMouseButtonDown (event.button.button, event.button.x, event.button.y); break; case SDL_MOUSEBUTTONUP: OnMouseButtonUp (event.button.button, event.button.x, event.button.y); break; case SDL_VIDEORESIZE: OnVideoResize (event.resize.w, event.resize.h); break; case SDL_QUIT: EngineSetStatus (EngineStatusStopping); break; default: break; } } } void ControllerBase::IMGUIFinish () { if (GetButtonState(MouseButtonLeft) == false) { uistate.activeitem = 0; } else { if (uistate.activeitem == 0) uistate.activeitem = -1; } // also reset the last keysym such that old values will not be reported uistate.last_keysym = SDLK_FIRST; uistate.last_key = SDLK_FIRST; uistate.keypressed_set.clear(); } /** \brief Keyboard processing */ bool ControllerBase::OnKeyDown (const SDL_keysym &keysym) { uistate.last_keysym = keysym.sym; uistate.last_key = keysym.sym; // Only when Unicode processing is activated store the unicode value if (SDL_EnableUNICODE(-1)) { uistate.last_unicode = keysym.unicode; // LogMessage ("Received key down of %s and unicode %d", convert_keycode(keysym.sym), keysym.unicode); } if (mBindings[keysym.sym].size () != 0 && GetButtonState(keysym.sym) == false) { QueueCommand (mBindings[keysym.sym]); } SetButtonState (keysym.sym, true); return false; } /** \brief Keyboard processing */ bool ControllerBase::OnKeyUp (const SDL_keysym &keysym) { SetButtonState (keysym.sym, false); uistate.keypressed_set.insert (keysym.sym); if (mBindings[keysym.sym].size () != 0) { if (mBindings[keysym.sym][0] == '+') { std::string upcommand = mBindings[keysym.sym]; upcommand[0] = '-'; QueueCommand (upcommand); return true; } } return false; } /** \brief Mouse processing */ bool ControllerBase::OnMouseButtonDown (Uint8 button, Uint16 xpos, Uint16 ypos) { MouseButton mouse_button = convert_sdl_button (button); mButtonStates.set(mouse_button, true); uistate.last_key = mouse_button; if (mView->mOverlayManager.SendMouseButtonDown (button, xpos, ypos)) return true; if (mBindings[mouse_button].size () != 0) { QueueCommand (mBindings[mouse_button]); return true; } return false; } /** \brief Mouse processing */ bool ControllerBase::OnMouseButtonUp (Uint8 button, Uint16 xpos, Uint16 ypos) { MouseButton mouse_button = convert_sdl_button (button); mButtonStates.set(mouse_button, false); uistate.keypressed_set.insert (mouse_button); if (mView->mOverlayManager.SendMouseButtonUp (button, xpos, ypos)) return true; if (mBindings[mouse_button].size () != 0) { if (mBindings[mouse_button][0] == '+') { std::string upcommand = mBindings[mouse_button]; upcommand[0] = '-'; QueueCommand (upcommand); return true; } } return false; } /** \brief Mouse processing */ bool ControllerBase::OnMouseMotion (const int xnew, const int ynew) { mMouseScreenPosition[0] = xnew; mMouseScreenPosition[1] = ynew; return false; } /** \brief Video */ bool ControllerBase::OnVideoResize (int width, int height) { mView->Resize (width, height); return true; } int convert_keystring (const char *key_val) { std::string keystr (key_val); // convert the keystr to lowercase for (std::string::iterator iter = keystr.begin(); iter != keystr.end(); iter++) (*iter) = tolower(*iter); // now we search through the table for he value we were given int i = 0; while (key_table[i].keynum != keytable_last) { if (keystr.compare(key_table[i].keystr) == 0) return key_table[i].keynum; i++; } return 0; } const char* convert_keycode (const int &keycode) { int i = 0; while (key_table[i].keynum != keytable_last) { if (key_table[i].keynum == keycode) return key_table[i].keystr; i++; } return NULL; } /* * Commands for the ControllerBase */ bool Cmd_Bind (const std::vector args) { if (ControllerInstance == NULL) { CommandSetErrorString("Could not bind key: Controller not yet initialized!"); return false; } if (args.size() != 2) { CommandSetErrorString("usage: bind "); return false; } int key = convert_keystring (args[0].c_str()); if (key == 0) { std::ostringstream error_msg; error_msg << "bind failed: invalid key '" << args[0] << '"'; CommandSetErrorString(error_msg.str()); return false; } if (!ControllerInstance->BindKey (key, args[1].c_str())) return false; return true; } void ControllerBase::OnRegisterCommands () { AddCommand ("bind", Cmd_Bind); } }