From 352e7283d6028091d07ad20e7fb86a5ad7380346 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 8 Apr 2016 18:03:09 +0200 Subject: [PATCH] Enable the usage of modifiers in bindKey calls (closing #158) --- .../interaction/interactionhandler.h | 57 +--- include/openspace/util/keys.h | 282 ++++++++++-------- src/CMakeLists.txt | 1 + src/interaction/interactionhandler.cpp | 170 +---------- src/interaction/interactionhandler_lua.inl | 12 +- src/util/keys.cpp | 99 ++++++ 6 files changed, 271 insertions(+), 350 deletions(-) create mode 100644 src/util/keys.cpp diff --git a/include/openspace/interaction/interactionhandler.h b/include/openspace/interaction/interactionhandler.h index 1b9041700a..2661603342 100644 --- a/include/openspace/interaction/interactionhandler.h +++ b/include/openspace/interaction/interactionhandler.h @@ -22,55 +22,6 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -//<<<<<<< HEAD -//#ifndef INTERACTIONHANDLER_H -//#define INTERACTIONHANDLER_H -// -//#include -//#include -//#include -// -//// std includes -//#include -//#include -//#include -//#include -// -//namespace openspace { -// -//// Forward declare to minimize dependencies -//class Camera; -//class SceneGraphNode; -//class ExternalControl; -// -//class InteractionHandler { -//public: -// InteractionHandler(void); -// InteractionHandler(const InteractionHandler& src); -// InteractionHandler& operator=(const InteractionHandler& rhs); -// virtual ~InteractionHandler(); -// -// void enable(); -// void disable(); -// const bool isEnabled() const; -// -// void connectDevices(); -// void addExternalControl(ExternalControl* controller); -// -// void setCamera(Camera *camera = nullptr); -// void setOrigin(SceneGraphNode* node); -// -// Camera* getCamera() const; -// const psc getOrigin() const; -// void lockControls(); -// void unlockControls(); -// -// void setFocusNode(SceneGraphNode *node); -// -// void orbit(const glm::quat &rotation); -// void rotate(const glm::quat &rotation); -// void distance(const PowerScaledScalar &distance, size_t iterations = 0); -//======= #ifndef __INTERACTIONHANDLER_H__ #define __INTERACTIONHANDLER_H__ @@ -132,7 +83,7 @@ public: void setRotation(const glm::quat& rotation); void resetKeyBindings(); - void bindKey(Key key, std::string lua); + void bindKey(Key key, KeyModifier modifier, std::string lua); void setInteractionSensitivity(float sensitivity); float interactionSensitivity() const; @@ -154,9 +105,8 @@ public: * interaction */ static scripting::ScriptEngine::LuaLibrary luaLibrary(); - -private: +private: friend class Controller; InteractionHandler(const InteractionHandler&) = delete; @@ -171,7 +121,8 @@ private: std::mutex _mutex; bool _validKeyLua; - std::multimap _keyLua; + + std::multimap _keyLua; float _controllerSensitivity; bool _invertRoll; diff --git a/include/openspace/util/keys.h b/include/openspace/util/keys.h index f57c143ead..9490b37732 100644 --- a/include/openspace/util/keys.h +++ b/include/openspace/util/keys.h @@ -62,144 +62,166 @@ namespace openspace { -enum class KeyAction { +enum class KeyAction : int { Release = 0, - Press = 1, - Repeat = 2 + Press = 1, + Repeat = 2 }; -enum class KeyModifier { - NoModifier = 0, - Shift = 0x0001, - Control = 0x0002, - Alt = 0x0004, - Super = 0x0008 +KeyAction operator|(KeyAction lhs, KeyAction rhs); +KeyAction operator|=(KeyAction& lhs, KeyAction rhs); + +enum class KeyModifier : int { + NoModifier = 0, + Shift = 0x0001, + Control = 0x0002, + Alt = 0x0004, + Super = 0x0008 }; +KeyModifier operator|(KeyModifier lhs, KeyModifier rhs); +KeyModifier operator|=(KeyModifier& lhs, KeyModifier rhs); + enum class Key { - Unknown = -1, - Space = 32, - Apostrophe = 39, - Comma = 44, - Minus = 45, - Period = 46, - Slash = 47, - Num0 = 48, - Num1 = 49, - Num2 = 50, - Num3 = 51, - Num4 = 52, - Num5 = 53, - Num6 = 54, - Num7 = 55, - Num8 = 56, - Num9 = 57, - SemiColon = 59, - Equal = 61, - A = 65, - B = 66, - C = 67, - D = 68, - E = 69, - F = 70, - G = 71, - H = 72, - I = 73, - J = 74, - K = 75, - L = 76, - M = 77, - N = 78, - O = 79, - P = 80, - Q = 81, - R = 82, - S = 83, - T = 84, - U = 85, - V = 86, - W = 87, - X = 88, - Y = 89, - Z = 90, - LeftBracket = 91, - BackSlash = 92, - RightBracket = 93, - GraveAccent = 96, - World1 = 161, - World2 = 162, - Escape = 256, - Enter = 257, - Tab = 258, - BackSpace = 259, - Insert = 260, - Delete = 261, - Right = 262, - Left = 263, - Down = 264, - Up = 265, - PageUp = 266, - PageDown = 267, - Home = 268, - End = 269, - CapsLock = 280, - ScrollLock = 281, - NumLock = 282, - PrintScreen = 283, - Pause = 284, - F1 = 290, - F2 = 291, - F3 = 292, - F4 = 293, - F5 = 294, - F6 = 295, - F7 = 296, - F8 = 297, - F9 = 298, - F10 = 299, - F11 = 300, - F12 = 301, - F13 = 302, - F14 = 303, - F15 = 304, - F16 = 305, - F17 = 306, - F18 = 307, - F19 = 308, - F20 = 309, - F21 = 310, - F22 = 311, - F23 = 312, - F24 = 313, - F25 = 314, - Keypad0 = 320, - Keypad1 = 321, - Keypad2 = 322, - Keypad3 = 323, - Keypad4 = 324, - Keypad5 = 325, - Keypad6 = 326, - Keypad7 = 327, - Keypad8 = 328, - Keypad9 = 329, - KeypadDecimal = 330, - KeypadDivide = 331, - KeypadMultiply = 332, - KeypadSubtract = 333, - KeypadAdd = 334, - KeypadEnter = 335, - LeftShift = 340, - LeftControl = 341, - LeftAlt = 342, - LeftSuper = 343, - RightShift = 344, - RightControl = 345, - RightAlt = 346, - RightSuper = 347, - Menu = 348, - Last = Menu + Unknown = -1, + Space = 32, + Apostrophe = 39, + Comma = 44, + Minus = 45, + Period = 46, + Slash = 47, + Num0 = 48, + Num1 = 49, + Num2 = 50, + Num3 = 51, + Num4 = 52, + Num5 = 53, + Num6 = 54, + Num7 = 55, + Num8 = 56, + Num9 = 57, + SemiColon = 59, + Equal = 61, + A = 65, + B = 66, + C = 67, + D = 68, + E = 69, + F = 70, + G = 71, + H = 72, + I = 73, + J = 74, + K = 75, + L = 76, + M = 77, + N = 78, + O = 79, + P = 80, + Q = 81, + R = 82, + S = 83, + T = 84, + U = 85, + V = 86, + W = 87, + X = 88, + Y = 89, + Z = 90, + LeftBracket = 91, + BackSlash = 92, + RightBracket = 93, + GraveAccent = 96, + World1 = 161, + World2 = 162, + Escape = 256, + Enter = 257, + Tab = 258, + BackSpace = 259, + Insert = 260, + Delete = 261, + Right = 262, + Left = 263, + Down = 264, + Up = 265, + PageUp = 266, + PageDown = 267, + Home = 268, + End = 269, + CapsLock = 280, + ScrollLock = 281, + NumLock = 282, + PrintScreen = 283, + Pause = 284, + F1 = 290, + F2 = 291, + F3 = 292, + F4 = 293, + F5 = 294, + F6 = 295, + F7 = 296, + F8 = 297, + F9 = 298, + F10 = 299, + F11 = 300, + F12 = 301, + F13 = 302, + F14 = 303, + F15 = 304, + F16 = 305, + F17 = 306, + F18 = 307, + F19 = 308, + F20 = 309, + F21 = 310, + F22 = 311, + F23 = 312, + F24 = 313, + F25 = 314, + Keypad0 = 320, + Keypad1 = 321, + Keypad2 = 322, + Keypad3 = 323, + Keypad4 = 324, + Keypad5 = 325, + Keypad6 = 326, + Keypad7 = 327, + Keypad8 = 328, + Keypad9 = 329, + KeypadDecimal = 330, + KeypadDivide = 331, + KeypadMultiply = 332, + KeypadSubtract = 333, + KeypadAdd = 334, + KeypadEnter = 335, + LeftShift = 340, + LeftControl = 341, + LeftAlt = 342, + LeftSuper = 343, + RightShift = 344, + RightControl = 345, + RightAlt = 346, + RightSuper = 347, + Menu = 348, + Last = Menu }; +struct KeyWithModifier { + Key key; + KeyModifier modifier; +}; + +KeyWithModifier stringToKey(std::string str); +bool operator<(const KeyWithModifier& lhs, const KeyWithModifier& rhs); + + +static const std::map KeyModifierMapping = { + { "SHIFT", KeyModifier::Shift }, + { "ALT", KeyModifier::Alt }, + { "CTRL", KeyModifier::Control }, + { "SUPER", KeyModifier::Super } +}; + static const std::map KeyMapping = { { "SPACE", Key::Space }, { "APOSTROPHE", Key::Apostrophe }, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8a941baf63..65e59b390a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -75,6 +75,7 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/util/boxgeometry.cpp ${OPENSPACE_BASE_DIR}/src/util/camera.cpp ${OPENSPACE_BASE_DIR}/src/util/factorymanager.cpp + ${OPENSPACE_BASE_DIR}/src/util/keys.cpp ${OPENSPACE_BASE_DIR}/src/util/openspacemodule.cpp ${OPENSPACE_BASE_DIR}/src/util/powerscaledcoordinate.cpp ${OPENSPACE_BASE_DIR}/src/util/powerscaledscalar.cpp diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index 4e68967c79..3865b2eb99 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -36,79 +36,11 @@ namespace { const std::string _loggerCat = "InteractionHandler"; - - openspace::Key stringToKey(std::string s) { - // key only uppercase - std::transform(s.begin(), s.end(), s.begin(), ::toupper); - - // default is unknown - auto it = openspace::KeyMapping.find(s); - if (it != openspace::KeyMapping.end()) - return it->second; - else - return openspace::Key::Unknown; - } } #include "interactionhandler_lua.inl" namespace openspace { - -//InteractionHandler::InteractionHandler() { -// // initiate pointers -// _camera = nullptr; -// _enabled = true; -// _node = nullptr; -// _dt = 0.0; -// _lastTrackballPos = glm::vec3(0.0, 0.0, 0.5); -// _leftMouseButtonDown = false; -// _isMouseBeingPressedAndHeld = false; -//} -// -//InteractionHandler::~InteractionHandler() { -// for (size_t i = 0; i < _controllers.size(); ++i) { -// delete _controllers[i]; -// } -//} -// -////void InteractionHandler::init() { -//// assert( ! this_); -//// this_ = new InteractionHandler(); -////} -//// -////void InteractionHandler::deinit() { -//// assert(this_); -//// delete this_; -//// this_ = nullptr; -////} -//// -////InteractionHandler& InteractionHandler::ref() { -//// assert(this_); -//// return *this_; -////} -// -////bool InteractionHandler::isInitialized() { -//// return this_ != nullptr; -////} -// -//void InteractionHandler::enable() { -// //assert(this_); -// _enabled = true; -//} -// -//void InteractionHandler::disable() { -// //assert(this_); -// _enabled = false; -//} -// -//const bool InteractionHandler::isEnabled() const { -// //assert(this_); -// if (_camera) -// return false; -// return _enabled; -//======= - -//namespace openspace { namespace interaction { InteractionHandler::InteractionHandler() @@ -179,59 +111,6 @@ void InteractionHandler::unlockControls() { _mutex.unlock(); } -//<<<<<<< HEAD -//void InteractionHandler::addExternalControl(ExternalControl* controller) { -// //assert(this_); -// if (controller != nullptr) { -// _controllers.push_back(controller); -// } -//} -// -//void InteractionHandler::setCamera(Camera *camera) { -// //assert(this_); -// _camera = camera; -//} -// -//void InteractionHandler::setOrigin(SceneGraphNode* node) { -// if (node) -// _node = node; -//} -// -//Camera * InteractionHandler::getCamera() const { -// //assert(this_); -// if (_enabled) { -// return _camera; -// } -// return nullptr; -//} -// -//const psc InteractionHandler::getOrigin() const { -// if (_node) -// return _node->worldPosition(); -// return psc(); -//} -// -//void InteractionHandler::lockControls() { -// //assert(this_); -// _cameraGuard.lock(); -//} -// -//void InteractionHandler::unlockControls() { -// //assert(this_); -// _cameraGuard.unlock(); -//} -// -//void InteractionHandler::setFocusNode(SceneGraphNode *node) { -// //assert(this_); -// _node = node; -//} -// -//void InteractionHandler::rotate(const glm::quat &rotation) { -// //assert(this_); -// lockControls(); -// _camera->rotate(rotation); -// unlockControls(); -//======= void InteractionHandler::update(double deltaTime) { _deltaTime = deltaTime; _mouseController->update(deltaTime); @@ -564,7 +443,7 @@ void InteractionHandler::keyboardCallback(Key key, KeyModifier modifier, KeyActi // iterate over key bindings _validKeyLua = true; - auto ret = _keyLua.equal_range(key); + auto ret = _keyLua.equal_range({ key, modifier }); for (auto it = ret.first; it != ret.second; ++it) { //OsEng.scriptEngine()->runScript(it->second); OsEng.scriptEngine().queueScript(it->second); @@ -574,51 +453,17 @@ void InteractionHandler::keyboardCallback(Key key, KeyModifier modifier, KeyActi } } } -// -//void InteractionHandler::mouseButtonCallback(int key, int action) { -// //if(mouseControl_ != nullptr) { -// // mouseControl_->mouseButtonCallback(key,action); -// //} -// if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_PRESS) -// _leftMouseButtonDown = true; -// else if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_RELEASE) { -// _leftMouseButtonDown = false; -// _isMouseBeingPressedAndHeld = false; -// } -//} -// -//void InteractionHandler::mousePositionCallback(int x, int y) { -// if (_leftMouseButtonDown) -// trackballRotate(x,y); -// -// //if(mouseControl_ != nullptr) { -// // mouseControl_->mousePosCallback(x,y); -// //} -//} -// -//void InteractionHandler::mouseScrollWheelCallback(int pos) { -// //if(mouseControl_ != nullptr) { -// // mouseControl_->mouseScrollCallback(pos); -// //} -// const float speed = 4.75f; -// const float dt = static_cast(_dt); -// if(pos < 0) { -// PowerScaledScalar dist(speed * dt, 0.0f); -// distance(dist); -// } else if(pos > 0) { -// PowerScaledScalar dist(-speed * dt, 0.0f); -// distance(dist); -// } -//} -// -// + void InteractionHandler::resetKeyBindings() { _keyLua.clear(); _validKeyLua = false; } -void InteractionHandler::bindKey(Key key, std::string lua) { - _keyLua.insert(std::make_pair(key, lua)); +void InteractionHandler::bindKey(Key key, KeyModifier modifier, std::string lua) { + _keyLua.insert({ + {key, modifier}, + lua + }); } scripting::ScriptEngine::LuaLibrary InteractionHandler::luaLibrary() { @@ -691,7 +536,6 @@ scripting::ScriptEngine::LuaLibrary InteractionHandler::luaLibrary() { }; } -//======= void InteractionHandler::setRotation(const glm::quat& rotation) { _camera->setRotation(rotation); diff --git a/src/interaction/interactionhandler_lua.inl b/src/interaction/interactionhandler_lua.inl index eeb7ca99c3..cf133964b2 100644 --- a/src/interaction/interactionhandler_lua.inl +++ b/src/interaction/interactionhandler_lua.inl @@ -76,16 +76,20 @@ int bindKey(lua_State* L) { if (command.empty()) return luaL_error(L, "Command string is empty"); - openspace::Key iKey = stringToKey(key); + openspace::KeyWithModifier iKey = openspace::stringToKey(key); - if (iKey == openspace::Key::Unknown) { + if (iKey.key == openspace::Key::Unknown) { LERROR("Could not find key '"<< key <<"'"); return 0; } - OsEng.interactionHandler().bindKey(iKey, command); - + OsEng.interactionHandler().bindKey( + iKey.key, + iKey.modifier, + command + ); + return 0; } diff --git a/src/util/keys.cpp b/src/util/keys.cpp new file mode 100644 index 0000000000..2384f503cb --- /dev/null +++ b/src/util/keys.cpp @@ -0,0 +1,99 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014-2016 * +* * +* Permission is hereby granted, free of charge, to any person obtaining a copy of this * +* software and associated documentation files (the "Software"), to deal in the Software * +* without restriction, including without limitation the rights to use, copy, modify, * +* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * +* permit persons to whom the Software is furnished to do so, subject to the following * +* conditions: * +* * +* The above copyright notice and this permission notice shall be included in all copies * +* or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +****************************************************************************************/ + +#include + +#include +#include + +#include +#include + +namespace { + const std::string _loggerCat = "Keys"; +} + +namespace openspace { + +KeyAction operator|(KeyAction lhs, KeyAction rhs) { + return static_cast( + static_cast>(lhs) | + static_cast>(rhs) + ); +} + +KeyAction operator|=(KeyAction& lhs, KeyAction rhs) { + lhs = (lhs | rhs); + return lhs; +} + +KeyModifier operator|(KeyModifier lhs, KeyModifier rhs) { + return static_cast( + static_cast>(lhs) | + static_cast>(rhs) + ); +} + +KeyModifier operator|=(KeyModifier& lhs, KeyModifier rhs) { + lhs = (lhs | rhs); + return lhs; +} + +KeyWithModifier stringToKey(std::string str) { + // key only uppercase + std::transform(str.begin(), str.end(), str.begin(), ::toupper); + + std::vector tokens = ghoul::tokenizeString(str, '+'); + + // default is unknown + Key k = Key::Unknown; + auto it = KeyMapping.find(tokens.back()); + if (it != KeyMapping.end()) + k = it->second; + + + KeyModifier m = KeyModifier::NoModifier; + std::for_each( + tokens.begin(), + tokens.end() - 1, + [&m](const std::string& s) { + auto it = KeyModifierMapping.find(s); + if (it != KeyModifierMapping.end()) + m |= it->second; + else + LERROR("Unknown modifier key '" << s << "'"); + } + ); + + return { k, m }; +} + +bool operator<(const KeyWithModifier& lhs, const KeyWithModifier& rhs) { + if (lhs.modifier == rhs.modifier) + return lhs.key < rhs.key; + else + return lhs.modifier < rhs.modifier; +} + +} // namespace openspace