From e4bec88a68843ef7ae4af4dc76c9b4872c2eb136 Mon Sep 17 00:00:00 2001 From: Michael Stopa Date: Wed, 30 Oct 2019 15:22:24 +0400 Subject: [PATCH] Implement mouse wheel bindings (bug #2679) --- CHANGELOG.md | 1 + CHANGELOG_PR.md | 1 + apps/launcher/advancedpage.cpp | 2 - apps/openmw/engine.cpp | 3 + apps/openmw/mwinput/inputmanagerimp.cpp | 84 +++++++-- apps/openmw/mwinput/inputmanagerimp.hpp | 51 +++--- components/sdlutil/events.hpp | 1 + components/sdlutil/sdlinputwrapper.cpp | 1 + .../reference/modding/settings/input.rst | 12 -- extern/oics/ICSInputControlSystem.cpp | 79 +++++++++ extern/oics/ICSInputControlSystem.h | 30 ++++ extern/oics/ICSInputControlSystem_mouse.cpp | 167 ++++++++++++++++++ files/settings-default.cfg | 3 - files/ui/advancedpage.ui | 10 -- 14 files changed, 386 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2e13e3f0..5a57c6cf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Bug #1515: Opening console masks dialogue, inventory menu Bug #1933: Actors can have few stocks of the same item Bug #2395: Duplicated plugins in the launcher when multiple data directories provide the same plugin + Bug #2679: Unable to map mouse wheel under control settings Bug #2969: Scripted items can stack Bug #2976: Data lines in global openmw.cfg take priority over user openmw.cfg Bug #2987: Editor: some chance and AI data fields can overflow diff --git a/CHANGELOG_PR.md b/CHANGELOG_PR.md index 71677af50..526e09f14 100644 --- a/CHANGELOG_PR.md +++ b/CHANGELOG_PR.md @@ -44,6 +44,7 @@ New Editor Features: - Land heightmap/shape editing and vertex selection (#5170) Bug Fixes: +- The Mouse Wheel can now be used for key bindings (#2679) - Scripted Items cannot be stacked anymore to avoid multiple script execution (#2969) - Stray text after an "else" statement is now ignored, like in the original engine, to handle mods which erroneously use "else if" statements (#3006) - "SetPos" and "SetPosition" commands now more closely replicate the original engine's behaviour (#3109) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index a8ff9a0ed..fe3afc6a8 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -84,7 +84,6 @@ bool Launcher::AdvancedPage::loadSettings() loadSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game"); // Input Settings - loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input"); loadSettingBool(grabCursorCheckBox, "grab cursor", "Input"); loadSettingBool(toggleSneakCheckBox, "toggle sneak", "Input"); @@ -145,7 +144,6 @@ void Launcher::AdvancedPage::saveSettings() saveSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game"); // Input Settings - saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input"); saveSettingBool(grabCursorCheckBox, "grab cursor", "Input"); saveSettingBool(toggleSneakCheckBox, "toggle sneak", "Input"); diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 4d8d47d51..1299fde0d 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -500,8 +500,11 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) if(boost::filesystem::exists(input2)) { boost::filesystem::copy_file(input2, keybinderUser); keybinderUserExists = boost::filesystem::exists(keybinderUser); + Log(Debug::Info) << "Loading keybindings file: " << keybinderUser; } } + else + Log(Debug::Info) << "Loading keybindings file: " << keybinderUser; // find correct path to the game controller bindings // File format for controller mappings is different for SDL <= 2.0.4, 2.0.5, and >= 2.0.6 diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 6e0f3375b..99b1118bf 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -464,6 +464,14 @@ namespace MWInput case A_ToggleDebug: MWBase::Environment::get().getWindowManager()->toggleDebugWindow(); break; + case A_ZoomIn: + if (mControlSwitch["playerviewswitch"] && mControlSwitch["playercontrols"] && !MWBase::Environment::get().getWindowManager()->isGuiMode()) + MWBase::Environment::get().getWorld()->setCameraDistance(ZOOM_SCALE, true, true); + break; + case A_ZoomOut: + if (mControlSwitch["playerviewswitch"] && mControlSwitch["playercontrols"] && !MWBase::Environment::get().getWindowManager()->isGuiMode()) + MWBase::Environment::get().getWorld()->setCameraDistance(-ZOOM_SCALE, true, true); + break; case A_QuickSave: quickSave(); break; @@ -750,7 +758,9 @@ namespace MWInput actionIsActive(A_MoveRight) || actionIsActive(A_Jump) || actionIsActive(A_Sneak) || - actionIsActive(A_TogglePOV)) + actionIsActive(A_TogglePOV) || + actionIsActive(A_ZoomIn) || + actionIsActive(A_ZoomOut) ) { resetIdleTime(); } else { @@ -938,6 +948,14 @@ namespace MWInput } } + void InputManager::mouseWheelMoved(const SDL_MouseWheelEvent &arg) + { + if (mInputBinder->detectingBindingState() || !mControlsDisabled) + mInputBinder->mouseWheelMoved(arg); + + mJoystickLastUsed = false; + } + void InputManager::mouseMoved(const SDLUtil::MouseMotionEvent &arg ) { mInputBinder->mouseMoved (arg); @@ -985,9 +1003,6 @@ namespace MWInput if (arg.zrel && mControlSwitch["playerviewswitch"] && mControlSwitch["playercontrols"]) //Check to make sure you are allowed to zoomout and there is a change { MWBase::Environment::get().getWorld()->changeVanityModeScale(static_cast(arg.zrel)); - - if (Settings::Manager::getBool("allow third person zoom", "Input")) - MWBase::Environment::get().getWorld()->setCameraDistance(static_cast(arg.zrel), true, true); } } } @@ -1447,6 +1462,10 @@ namespace MWInput defaultMouseButtonBindings[A_Inventory] = SDL_BUTTON_RIGHT; defaultMouseButtonBindings[A_Use] = SDL_BUTTON_LEFT; + std::map defaultMouseWheelBindings; + defaultMouseWheelBindings[A_ZoomIn] = ICS::InputControlSystem::MouseWheelClick::UP; + defaultMouseWheelBindings[A_ZoomOut] = ICS::InputControlSystem::MouseWheelClick::DOWN; + for (int i = 0; i < A_Last; ++i) { ICS::Control* control; @@ -1465,6 +1484,7 @@ namespace MWInput if (!controlExists || force || ( mInputBinder->getKeyBinding (control, ICS::Control::INCREASE) == SDL_SCANCODE_UNKNOWN && mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE) == ICS_MAX_DEVICE_BUTTONS + && mInputBinder->getMouseWheelBinding(control, ICS::Control::INCREASE) == ICS::InputControlSystem::MouseWheelClick::UNASSIGNED )) { clearAllKeyBindings(control); @@ -1481,6 +1501,12 @@ namespace MWInput control->setInitialValue(0.0f); mInputBinder->addMouseButtonBinding (control, defaultMouseButtonBindings[i], ICS::Control::INCREASE); } + else if (defaultMouseWheelBindings.find(i) != defaultMouseWheelBindings.end() + && (force || !mInputBinder->isMouseWheelBound(defaultMouseWheelBindings[i]))) + { + control->setInitialValue(0.f); + mInputBinder->addMouseWheelBinding(control, defaultMouseWheelBindings[i], ICS::Control::INCREASE); + } if (i == A_LookLeftRight && !mInputBinder->isKeyBound(SDL_SCANCODE_KP_4) && !mInputBinder->isKeyBound(SDL_SCANCODE_KP_6)) { @@ -1571,6 +1597,10 @@ namespace MWInput if (action == A_Screenshot) return "Screenshot"; + else if (action == A_ZoomIn) + return "Zoom In"; + else if (action == A_ZoomOut) + return "Zoom Out"; descriptions[A_Use] = "sUse"; descriptions[A_Activate] = "sActivate"; @@ -1623,10 +1653,25 @@ namespace MWInput SDL_Scancode key = mInputBinder->getKeyBinding (c, ICS::Control::INCREASE); unsigned int mouse = mInputBinder->getMouseButtonBinding (c, ICS::Control::INCREASE); + ICS::InputControlSystem::MouseWheelClick wheel = mInputBinder->getMouseWheelBinding(c, ICS::Control::INCREASE); if (key != SDL_SCANCODE_UNKNOWN) return MyGUI::TextIterator::toTagsString(mInputBinder->scancodeToString (key)); else if (mouse != ICS_MAX_DEVICE_BUTTONS) return "#{sMouse} " + std::to_string(mouse); + else if (wheel != ICS::InputControlSystem::MouseWheelClick::UNASSIGNED) + switch (wheel) + { + case ICS::InputControlSystem::MouseWheelClick::UP: + return "Mouse Wheel Up"; + case ICS::InputControlSystem::MouseWheelClick::DOWN: + return "Mouse Wheel Down"; + case ICS::InputControlSystem::MouseWheelClick::RIGHT: + return "Mouse Wheel Right"; + case ICS::InputControlSystem::MouseWheelClick::LEFT: + return "Mouse Wheel Left"; + default: + return "#{sNone}"; + } else return "#{sNone}"; } @@ -1713,6 +1758,8 @@ namespace MWInput ret.push_back(A_MoveLeft); ret.push_back(A_MoveRight); ret.push_back(A_TogglePOV); + ret.push_back(A_ZoomIn); + ret.push_back(A_ZoomOut); ret.push_back(A_Run); ret.push_back(A_AlwaysRun); ret.push_back(A_Sneak); @@ -1751,6 +1798,8 @@ namespace MWInput { std::vector ret; ret.push_back(A_TogglePOV); + ret.push_back(A_ZoomIn); + ret.push_back(A_ZoomOut); ret.push_back(A_Sneak); ret.push_back(A_Activate); ret.push_back(A_Use); @@ -1790,13 +1839,6 @@ namespace MWInput mInputBinder->enableDetectingBindingState (c, ICS::Control::INCREASE); } - void InputManager::mouseAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , ICS::InputControlSystem::NamedAxis axis, ICS::Control::ControlChangingDirection direction) - { - // we don't want mouse movement bindings - return; - } - void InputManager::keyBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control , SDL_Scancode key, ICS::Control::ControlChangingDirection direction) { @@ -1828,6 +1870,13 @@ namespace MWInput MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); } + void InputManager::mouseAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , ICS::InputControlSystem::NamedAxis axis, ICS::Control::ControlChangingDirection direction) + { + // we don't want mouse movement bindings + return; + } + void InputManager::mouseButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control , unsigned int button, ICS::Control::ControlChangingDirection direction) { @@ -1839,6 +1888,17 @@ namespace MWInput MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); } + void InputManager::mouseWheelBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , ICS::InputControlSystem::MouseWheelClick click, ICS::Control::ControlChangingDirection direction) + { + if(!mDetectingKeyboard) + return; + clearAllKeyBindings(control); + control->setInitialValue(0.0f); + ICS::DetectingBindingListener::mouseWheelBindingDetected(ICS, control, click, direction); + MWBase::Environment::get().getWindowManager()->notifyInputActionBound(); + } + void InputManager::joystickAxisBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control , int axis, ICS::Control::ControlChangingDirection direction) { @@ -1873,6 +1933,8 @@ namespace MWInput mInputBinder->removeKeyBinding (mInputBinder->getKeyBinding (control, ICS::Control::INCREASE)); if (mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS) mInputBinder->removeMouseButtonBinding (mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE)); + if (mInputBinder->getMouseWheelBinding (control, ICS::Control::INCREASE) != ICS::InputControlSystem::MouseWheelClick::UNASSIGNED) + mInputBinder->removeMouseWheelBinding (mInputBinder->getMouseWheelBinding(control, ICS::Control::INCREASE)); } void InputManager::clearAllControllerBindings (ICS::Control* control) diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index cd7047824..12ea9f3fa 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -56,6 +56,7 @@ struct SDL_Window; namespace MWInput { + const float ZOOM_SCALE = 120.f; /// Used for scrolling camera in and out /** * @brief Class that handles all input and key bindings for OpenMW. @@ -120,6 +121,8 @@ namespace MWInput virtual void mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ); virtual void mouseMoved( const SDLUtil::MouseMotionEvent &arg ); + virtual void mouseWheelMoved( const SDL_MouseWheelEvent &arg); + virtual void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &arg); virtual void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &arg); virtual void axisMoved(int deviceID, const SDL_ControllerAxisEvent &arg); @@ -133,15 +136,18 @@ namespace MWInput virtual void channelChanged(ICS::Channel* channel, float currentValue, float previousValue); - virtual void mouseAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , ICS::InputControlSystem::NamedAxis axis, ICS::Control::ControlChangingDirection direction); - virtual void keyBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control , SDL_Scancode key, ICS::Control::ControlChangingDirection direction); + virtual void mouseAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , ICS::InputControlSystem::NamedAxis axis, ICS::Control::ControlChangingDirection direction); + virtual void mouseButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control , unsigned int button, ICS::Control::ControlChangingDirection direction); + virtual void mouseWheelBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , ICS::InputControlSystem::MouseWheelClick click, ICS::Control::ControlChangingDirection direction); + virtual void joystickAxisBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control , int axis, ICS::Control::ControlChangingDirection direction); @@ -268,33 +274,33 @@ namespace MWInput A_Unused, - A_Screenshot, // Take a screenshot + A_Screenshot, // Take a screenshot - A_Inventory, // Toggle inventory screen + A_Inventory, // Toggle inventory screen - A_Console, // Toggle console screen + A_Console, // Toggle console screen - A_MoveLeft, // Move player left / right + A_MoveLeft, // Move player left / right A_MoveRight, - A_MoveForward, // Forward / Backward + A_MoveForward, // Forward / Backward A_MoveBackward, A_Activate, - A_Use, //Use weapon, spell, etc. + A_Use, //Use weapon, spell, etc. A_Jump, - A_AutoMove, //Toggle Auto-move forward - A_Rest, //Rest - A_Journal, //Journal - A_Weapon, //Draw/Sheath weapon - A_Spell, //Ready/Unready Casting - A_Run, //Run when held - A_CycleSpellLeft, //cycling through spells + A_AutoMove, //Toggle Auto-move forward + A_Rest, //Rest + A_Journal, //Journal + A_Weapon, //Draw/Sheath weapon + A_Spell, //Ready/Unready Casting + A_Run, //Run when held + A_CycleSpellLeft, //cycling through spells A_CycleSpellRight, - A_CycleWeaponLeft,//Cycling through weapons + A_CycleWeaponLeft, //Cycling through weapons A_CycleWeaponRight, - A_ToggleSneak, //Toggles Sneak - A_AlwaysRun, //Toggle Walking/Running + A_ToggleSneak, //Toggles Sneak + A_AlwaysRun, //Toggle Walking/Running A_Sneak, A_QuickSave, @@ -322,12 +328,15 @@ namespace MWInput A_ToggleDebug, - A_LookUpDown, //Joystick look + A_LookUpDown, //Joystick look A_LookLeftRight, A_MoveForwardBackward, A_MoveLeftRight, - A_Last // Marker for the last item + A_ZoomIn, + A_ZoomOut, + + A_Last // Marker for the last item }; }; } diff --git a/components/sdlutil/events.hpp b/components/sdlutil/events.hpp index 7c79470ff..b7a736617 100644 --- a/components/sdlutil/events.hpp +++ b/components/sdlutil/events.hpp @@ -30,6 +30,7 @@ public: virtual void mouseMoved( const MouseMotionEvent &arg ) = 0; virtual void mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id ) = 0; virtual void mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ) = 0; + virtual void mouseWheelMoved( const SDL_MouseWheelEvent &arg) = 0; }; class KeyListener diff --git a/components/sdlutil/sdlinputwrapper.cpp b/components/sdlutil/sdlinputwrapper.cpp index c67edfbf3..c804f0b2d 100644 --- a/components/sdlutil/sdlinputwrapper.cpp +++ b/components/sdlutil/sdlinputwrapper.cpp @@ -77,6 +77,7 @@ InputWrapper::InputWrapper(SDL_Window* window, osg::ref_ptr v break; case SDL_MOUSEWHEEL: mMouseListener->mouseMoved(_packageMouseMotion(evt)); + mMouseListener->mouseWheelMoved(evt.wheel); break; case SDL_MOUSEBUTTONDOWN: mMouseListener->mousePressed(evt.button, evt.button.button); diff --git a/docs/source/reference/modding/settings/input.rst b/docs/source/reference/modding/settings/input.rst index d481321c2..ef93b72cb 100644 --- a/docs/source/reference/modding/settings/input.rst +++ b/docs/source/reference/modding/settings/input.rst @@ -54,18 +54,6 @@ based on whether the caps lock key was on or off at the time you exited. This settings can be toggled in game by pressing the CapsLock key and exiting. -allow third person zoom ------------------------ - -:Type: boolean -:Range: True/False -:Default: False - -Allow zooming in and out using the middle mouse wheel in third person view. -This feature may not work correctly if the mouse wheel is bound to other actions, -and may be triggered accidentally in some cases, so is disabled by default. -This setting can only be configured by editing the settings configuration file. - camera sensitivity ------------------ diff --git a/extern/oics/ICSInputControlSystem.cpp b/extern/oics/ICSInputControlSystem.cpp index 8bb9c4638..1be8a8b37 100644 --- a/extern/oics/ICSInputControlSystem.cpp +++ b/extern/oics/ICSInputControlSystem.cpp @@ -226,6 +226,15 @@ namespace ICS loadJoystickButtonBinders(xmlControl); + /* ---------------------------------------------------------------------------------------- + * OPENMW CODE STARTS HERE + * Mouse Wheel support added by Michael Stopa (Stomy) */ + + loadMouseWheelBinders(xmlControl); + + /* OPENMW CODE ENDS HERE + * ------------------------------------------------------------------------------------- */ + // Attach controls to channels TiXmlElement* xmlChannel = xmlControl->FirstChildElement("Channel"); while(xmlChannel) @@ -307,6 +316,15 @@ namespace ICS mControlsMouseButtonBinderMap.clear(); mControlsJoystickButtonBinderMap.clear(); + /* ---------------------------------------------------------------------------------------- + * OPENMW CODE STARTS HERE + * Mouse Wheel support added by Michael Stopa (Stomy) */ + + mControlsMouseWheelBinderMap.clear(); + + /* OPENMW CODE ENDS HERE + * ------------------------------------------------------------------------------------- */ + ICS_LOG(" - InputControlSystem deleted - "); } @@ -491,6 +509,67 @@ namespace ICS control.InsertEndChild(binder); } + /* ---------------------------------------------------------------------------------------- + * OPENMW CODE STARTS HERE + * Mouse Wheel support added by Stomy */ + + if(getMouseWheelBinding(*o, Control::INCREASE) != MouseWheelClick::UNASSIGNED) + { + TiXmlElement binder( "MouseWheelBinder" ); + MouseWheelClick click = getMouseWheelBinding(*o, Control::INCREASE); + bool skip = false; + switch (click) { + case MouseWheelClick::UP: { + binder.SetAttribute("button", "UP"); + } break; + case MouseWheelClick::DOWN: { + binder.SetAttribute("button", "DOWN"); + } break; + case MouseWheelClick::RIGHT: { + binder.SetAttribute("button", "RIGHT"); + } break; + case MouseWheelClick::LEFT: { + binder.SetAttribute("button", "LEFT"); + } break; + default: { + skip = true; + } break; + } + binder.SetAttribute( "direction", "INCREASE" ); + if (!skip) + control.InsertEndChild(binder); + } + + if(getMouseWheelBinding(*o, Control::DECREASE) != MouseWheelClick::UNASSIGNED) + { + TiXmlElement binder( "MouseWheelBinder" ); + MouseWheelClick click = getMouseWheelBinding(*o, Control::INCREASE); + bool skip = false; + switch (click) { + case MouseWheelClick::UP: { + binder.SetAttribute("button", "UP"); + } break; + case MouseWheelClick::DOWN: { + binder.SetAttribute("button", "DOWN"); + } break; + case MouseWheelClick::RIGHT: { + binder.SetAttribute("button", "RIGHT"); + } break; + case MouseWheelClick::LEFT: { + binder.SetAttribute("button", "LEFT"); + } break; + default: { + skip = true; + } break; + } + binder.SetAttribute( "direction", "DECREASE" ); + if (!skip) + control.InsertEndChild(binder); + } + + /* OPENMW CODE ENDS HERE + * ------------------------------------------------------------------------------------- */ + if(getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::INCREASE) != ICS_MAX_DEVICE_BUTTONS) { diff --git a/extern/oics/ICSInputControlSystem.h b/extern/oics/ICSInputControlSystem.h index 0e8e6ecad..3e808dd2e 100644 --- a/extern/oics/ICSInputControlSystem.h +++ b/extern/oics/ICSInputControlSystem.h @@ -214,6 +214,26 @@ namespace ICS Uint16 mClientWidth; Uint16 mClientHeight; + + /* ---------------------------------------------------------------------------------------- + * OPENMW CODE STARTS HERE + * Mouse Wheel support added by Michael Stopa (Stomy) */ + + public: + enum class MouseWheelClick : int { UNASSIGNED = 0, UP = 1, DOWN = 2, LEFT = 3, RIGHT = 4}; + + void mouseWheelMoved(const SDL_MouseWheelEvent &evt); + void addMouseWheelBinding(Control* control, MouseWheelClick click, Control::ControlChangingDirection direction); + void removeMouseWheelBinding(MouseWheelClick click); + MouseWheelClick getMouseWheelBinding(Control* control, ICS::Control::ControlChangingDirection direction); + bool isMouseWheelBound(MouseWheelClick button) const; + + protected: + void loadMouseWheelBinders(TiXmlElement* xmlControlNode); + ControlsButtonBinderMapType mControlsMouseWheelBinderMap; + + /* OPENMW CODE ENDS HERE + * ------------------------------------------------------------------------------------- */ }; class DllExport DetectingBindingListener @@ -234,6 +254,16 @@ namespace ICS virtual void joystickButtonBindingDetected(InputControlSystem* ICS, int deviceID, Control* control , unsigned int button, Control::ControlChangingDirection direction); + /* ---------------------------------------------------------------------------------------- + * OPENMW CODE STARTS HERE + * Mouse Wheel support added by Michael Stopa (Stomy) */ + + virtual void mouseWheelBindingDetected(InputControlSystem* ICS, Control* control, + InputControlSystem::MouseWheelClick click, + Control::ControlChangingDirection direction); + + /* OPENMW CODE ENDS HERE + * ------------------------------------------------------------------------------------- */ }; extern const float ICS_MAX; diff --git a/extern/oics/ICSInputControlSystem_mouse.cpp b/extern/oics/ICSInputControlSystem_mouse.cpp index e389bc981..09404bfdd 100644 --- a/extern/oics/ICSInputControlSystem_mouse.cpp +++ b/extern/oics/ICSInputControlSystem_mouse.cpp @@ -396,4 +396,171 @@ namespace ICS ICS->cancelDetectingBindingState(); } + /* ---------------------------------------------------------------------------------------- + * OPENMW CODE STARTS HERE + * Mouse Wheel support added by Michael Stopa (Stomy) */ + + void InputControlSystem::loadMouseWheelBinders(TiXmlElement* xmlControlNode) + { + TiXmlElement* xmlMouseWheelBinder = xmlControlNode->FirstChildElement("MouseWheelBinder"); + while (xmlMouseWheelBinder) + { + Control::ControlChangingDirection dir = Control::STOP; + if (std::string(xmlMouseWheelBinder->Attribute("direction")) == "INCREASE") + { + dir = Control::INCREASE; + } + else if (std::string(xmlMouseWheelBinder->Attribute("direction")) == "DECREASE") + { + dir = Control::DECREASE; + } + + MouseWheelClick click = MouseWheelClick::UNASSIGNED; + if (std::string(xmlMouseWheelBinder->Attribute("button")) == "UP") + { + click = MouseWheelClick::UP; + } + else if (std::string(xmlMouseWheelBinder->Attribute("button")) == "DOWN") + { + click = MouseWheelClick::DOWN; + } + else if (std::string(xmlMouseWheelBinder->Attribute("button")) == "DOWN") + { + click = MouseWheelClick::RIGHT; + } + else if (std::string(xmlMouseWheelBinder->Attribute("button")) == "DOWN") + { + click = MouseWheelClick::LEFT; + } + + addMouseWheelBinding(mControls.back(), click, dir); + xmlMouseWheelBinder = xmlMouseWheelBinder->NextSiblingElement("MouseWheelBinder"); + } + } + + void InputControlSystem::addMouseWheelBinding( + Control* control, + MouseWheelClick click, + Control::ControlChangingDirection direction) + { + ICS_LOG("\tAdding MouseWheelBinder [button=" + + ToString(static_cast(click)) + ", direction=" + + ToString(direction) + "]"); + + ControlButtonBinderItem controlButtonBinderItem; + controlButtonBinderItem.control = control; + controlButtonBinderItem.direction = direction; + mControlsMouseWheelBinderMap[static_cast(click)] = controlButtonBinderItem; + } + + void InputControlSystem::removeMouseWheelBinding(MouseWheelClick click) + { + ControlsAxisBinderMapType::iterator it = mControlsMouseWheelBinderMap.find(static_cast(click)); + if (it != mControlsMouseWheelBinderMap.end()) + { + mControlsMouseWheelBinderMap.erase(it); + } + } + + InputControlSystem::MouseWheelClick InputControlSystem::getMouseWheelBinding( + Control* control, + ICS::Control::ControlChangingDirection direction) + { + ControlsAxisBinderMapType::iterator it = mControlsMouseWheelBinderMap.begin(); + while (it != mControlsMouseWheelBinderMap.end()) + { + if (it->first > 0 && it->second.control == control && it->second.direction == direction) + { + return (MouseWheelClick)(it->first); + } + ++it; + } + + return MouseWheelClick::UNASSIGNED; + } + + bool InputControlSystem::isMouseWheelBound(MouseWheelClick button) const + { + return mControlsMouseWheelBinderMap.find(static_cast(button)) != mControlsMouseWheelBinderMap.end(); + } + + void InputControlSystem::mouseWheelMoved(const SDL_MouseWheelEvent &evt) + { + if (mActive) + { + MouseWheelClick click = MouseWheelClick::UNASSIGNED; + int value; + if (evt.y != 0) + { + value = evt.y; + if (evt.direction == SDL_MOUSEWHEEL_FLIPPED) + value *= -1; + if (value > 0) + click = MouseWheelClick::UP; + else + click = MouseWheelClick::DOWN; + } + else if (evt.x != 0) + { + value = evt.x; + if (evt.direction == SDL_MOUSEWHEEL_FLIPPED) + value *= -1; + if (value > 0) + click = MouseWheelClick::RIGHT; + else + click = MouseWheelClick::LEFT; + } + else + return; + + if(!mDetectingBindingControl) + { + // This assumes a single event is sent for every single mouse wheel direction, if they are + // buffered up then all bindings will have to be resolved on every invocation of this function + + ControlButtonBinderItem wheelBinderItem = mControlsMouseWheelBinderMap[static_cast(click)]; + Control* control = wheelBinderItem.control; + if (control) + { + control->setIgnoreAutoReverse(false); + if (wheelBinderItem.direction == Control::INCREASE) + { + control->setValue(static_cast(std::abs(value))); + control->setChangingDirection(Control::STOP); + } + else if (wheelBinderItem.direction == Control::DECREASE) + { + control->setValue(static_cast(std::abs(value))); + control->setChangingDirection(Control::STOP); + } + } + } + else if(mDetectingBindingListener) + { + mDetectingBindingListener->mouseWheelBindingDetected(this, + mDetectingBindingControl, click, mDetectingBindingDirection); + } + } + } + + void DetectingBindingListener::mouseWheelBindingDetected( + InputControlSystem* ICS, + Control* control, + InputControlSystem::MouseWheelClick click, + Control::ControlChangingDirection direction) + { + ICS->removeMouseWheelBinding(click); + + InputControlSystem::MouseWheelClick oldClick = ICS->getMouseWheelBinding(control, direction); + if (oldClick != InputControlSystem::MouseWheelClick::UNASSIGNED) + { + ICS->removeMouseWheelBinding(oldClick); + } + + ICS->addMouseWheelBinding(control, click, direction); + ICS->cancelDetectingBindingState(); + } + + /* OPENMW CODE ENDS HERE + * ------------------------------------------------------------------------------------- */ } diff --git a/files/settings-default.cfg b/files/settings-default.cfg index f3209c519..9695e4158 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -348,9 +348,6 @@ toggle sneak = false # Player is running by default. always run = false -# Zoom in and out from player in third person view with mouse wheel. -allow third person zoom = false - # Camera sensitivity when not in GUI mode. (>0.0, e.g. 0.1 to 5.0). camera sensitivity = 1.0 diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index 152ab6411..7421f7f78 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -178,16 +178,6 @@ Input - - - - <html><head/><body><p>Allow zooming in and out using the middle mouse wheel in third person view. This feature may not work correctly if the mouse wheel is bound to other actions, and may be triggered accidentally in some cases, so is disabled by default.</p></body></html> - - - Allow third person zoom - - -