From 935cccf9745dc04c37a85321bed9adef557f9831 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 15 Dec 2014 15:23:03 +0100 Subject: [PATCH] Implement weapon/spell cycling hotkeys (Fixes #1024) --- apps/openmw/mwbase/windowmanager.hpp | 5 +++ apps/openmw/mwgui/inventorywindow.cpp | 48 +++++++++++++++++++++++ apps/openmw/mwgui/inventorywindow.hpp | 3 ++ apps/openmw/mwgui/sortfilteritemmodel.cpp | 32 +++++++++------ apps/openmw/mwgui/sortfilteritemmodel.hpp | 4 ++ apps/openmw/mwgui/spellmodel.cpp | 4 ++ apps/openmw/mwgui/spellwindow.cpp | 21 ++++++++++ apps/openmw/mwgui/spellwindow.hpp | 3 ++ apps/openmw/mwgui/windowmanagerimp.cpp | 10 +++++ apps/openmw/mwgui/windowmanagerimp.hpp | 5 +++ apps/openmw/mwinput/inputmanagerimp.cpp | 25 ++++++++++++ 11 files changed, 148 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index d4f1afa32..fb35157e8 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -342,6 +342,11 @@ namespace MWBase virtual void setWerewolfOverlay(bool set) = 0; virtual void toggleDebugWindow() = 0; + + /// Cycle to next or previous spell + virtual void cycleSpell(bool next) = 0; + /// Cycle to next or previous weapon + virtual void cycleWeapon(bool next) = 0; }; } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index d1eeba157..4fbfc2c67 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -27,6 +27,19 @@ #include "tradewindow.hpp" #include "container.hpp" +namespace +{ + + bool isRightHandWeapon(const MWWorld::Ptr& item) + { + if (item.getClass().getTypeName() != typeid(ESM::Weapon).name()) + return false; + std::vector equipmentSlots = item.getClass().getEquipmentSlots(item).first; + return (!equipmentSlots.empty() && equipmentSlots.front() == MWWorld::InventoryStore::Slot_CarriedRight); + } + +} + namespace MWGui { @@ -599,4 +612,39 @@ namespace MWGui MWBase::Environment::get().getMechanicsManager()->itemTaken(player, newObject, count); } + + void InventoryWindow::cycle(bool next) + { + ItemModel::ModelIndex selected = 0; + // not using mSortFilterModel as we only need sorting, not filtering + SortFilterItemModel model(new InventoryItemModel(MWBase::Environment::get().getWorld()->getPlayerPtr())); + model.setSortByType(false); + model.update(); + if (model.getItemCount() == 0) + return; + for (ItemModel::ModelIndex i=0; imData.mCost; int eSkill = mActor.getClass().getSkill(mActor, ESM::Skill::Enchant); int castCost = std::max(1.f, enchantCost - (enchantCost / 100) * (eSkill - 10)); diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 1da9635db..37747f957 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -160,4 +160,25 @@ namespace MWGui updateSpells(); } + + void SpellWindow::cycle(bool next) + { + mSpellView->setModel(new SpellModel(MWBase::Environment::get().getWorld()->getPlayerPtr())); + mSpellView->getModel()->update(); + + SpellModel::ModelIndex selected = 0; + for (SpellModel::ModelIndex i = 0; igetModel()->getItemCount()); ++i) + { + if (mSpellView->getModel()->getItem(i).mSelected) + selected = i; + } + + selected += next ? 1 : -1; + int itemcount = mSpellView->getModel()->getItemCount(); + if (itemcount == 0) + return; + selected = (selected + itemcount) % itemcount; + + onModelIndexSelected(selected); + } } diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp index 2f7319cb9..650218d30 100644 --- a/apps/openmw/mwgui/spellwindow.hpp +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -21,6 +21,9 @@ namespace MWGui void onFrame(float dt) { NoDrop::onFrame(dt); } + /// Cycle to next/previous spell + void cycle(bool next); + protected: MyGUI::Widget* mEffectBox; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 26f14572f..9d24fb19b 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1820,4 +1820,14 @@ namespace MWGui mDebugWindow->setVisible(!mDebugWindow->isVisible()); } + void WindowManager::cycleSpell(bool next) + { + mSpellWindow->cycle(next); + } + + void WindowManager::cycleWeapon(bool next) + { + mInventoryWindow->cycle(next); + } + } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 94d8a93db..015f200d5 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -338,6 +338,11 @@ namespace MWGui virtual void toggleDebugWindow(); + /// Cycle to next or previous spell + virtual void cycleSpell(bool next); + /// Cycle to next or previous weapon + virtual void cycleWeapon(bool next); + private: bool mConsoleOnlyScripts; diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index b0d2bfeff..2f6149f09 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -286,6 +286,18 @@ namespace MWInput case A_QuickLoad: quickLoad(); break; + case A_CycleSpellLeft: + MWBase::Environment::get().getWindowManager()->cycleSpell(false); + break; + case A_CycleSpellRight: + MWBase::Environment::get().getWindowManager()->cycleSpell(true); + break; + case A_CycleWeaponLeft: + MWBase::Environment::get().getWindowManager()->cycleWeapon(false); + break; + case A_CycleWeaponRight: + MWBase::Environment::get().getWindowManager()->cycleWeapon(true); + break; } } } @@ -894,6 +906,11 @@ namespace MWInput defaultKeyBindings[A_MoveRight] = SDL_SCANCODE_D; defaultKeyBindings[A_ToggleWeapon] = SDL_SCANCODE_F; defaultKeyBindings[A_ToggleSpell] = SDL_SCANCODE_R; + defaultKeyBindings[A_CycleSpellLeft] = SDL_SCANCODE_MINUS; + defaultKeyBindings[A_CycleSpellRight] = SDL_SCANCODE_EQUALS; + defaultKeyBindings[A_CycleWeaponLeft] = SDL_SCANCODE_LEFTBRACKET; + defaultKeyBindings[A_CycleWeaponRight] = SDL_SCANCODE_RIGHTBRACKET; + defaultKeyBindings[A_QuickKeysMenu] = SDL_SCANCODE_F1; defaultKeyBindings[A_Console] = SDL_SCANCODE_GRAVE; defaultKeyBindings[A_Run] = SDL_SCANCODE_LSHIFT; @@ -972,6 +989,10 @@ namespace MWInput descriptions[A_MoveRight] = "sRight"; descriptions[A_ToggleWeapon] = "sReady_Weapon"; descriptions[A_ToggleSpell] = "sReady_Magic"; + descriptions[A_CycleSpellLeft] = "sPrevSpell"; + descriptions[A_CycleSpellRight] = "sNextSpell"; + descriptions[A_CycleWeaponLeft] = "sPrevWeapon"; + descriptions[A_CycleWeaponRight] = "sNextWeapon"; descriptions[A_Console] = "sConsoleTitle"; descriptions[A_Run] = "sRun"; descriptions[A_Sneak] = "sCrouch_Sneak"; @@ -1032,6 +1053,10 @@ namespace MWInput ret.push_back(A_Use); ret.push_back(A_ToggleWeapon); ret.push_back(A_ToggleSpell); + ret.push_back(A_CycleSpellLeft); + ret.push_back(A_CycleSpellRight); + ret.push_back(A_CycleWeaponLeft); + ret.push_back(A_CycleWeaponRight); ret.push_back(A_AutoMove); ret.push_back(A_Jump); ret.push_back(A_Inventory);