diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 6ab2c862d4..658eedfcd2 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -3,6 +3,8 @@ #include #include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/scriptmanager.hpp" @@ -88,8 +90,13 @@ namespace MWGui name += MWGui::ToolTips::getSoulString(object.getCellRef()); dialog->openCountDialog(name, "#{sTake}", count); dialog->eventOkClicked.clear(); - dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::dragItem); + if (Settings::gui().mControllerMenus && !mUsingGamepadGuiCursor) + dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::takeItem); + else + dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::dragItem); } + else if (Settings::gui().mControllerMenus && !mUsingGamepadGuiCursor) + takeItem(nullptr, count); else dragItem(nullptr, count); } @@ -105,6 +112,30 @@ namespace MWGui mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count); } + void ContainerWindow::takeItem(MyGUI::Widget* sender, int count) + { + if (!mModel) + return; + + const ItemStack& item = mModel->getItem(mSelectedItem); + if (!onTakeItem(item, count)) + return; + + MWGui::InventoryWindow* inventoryWindow + = MWBase::Environment::get().getWindowManager()->getInventoryWindow(); + ItemModel* playerModel = inventoryWindow->getModel(); + + mModel->moveItem(item, count, playerModel); + + inventoryWindow->updateItemView(); + mItemView->update(); + + // play the item's sound + MWWorld::Ptr itemBase = item.mBase; + const ESM::RefId& sound = itemBase.getClass().getUpSoundId(itemBase); + MWBase::Environment::get().getWindowManager()->playSound(sound); + } + void ContainerWindow::dropItem() { if (!mModel) @@ -320,4 +351,51 @@ namespace MWGui if (mModel && mModel->usesContainer(ptr)) MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); } + + bool ContainerWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) + { + if (arg.button == SDL_CONTROLLER_BUTTON_A) + { + if (mUsingGamepadGuiCursor) + return false; + + int index = mItemView->getControllerFocus(); + if (index >= 0 && index < mItemView->getItemCount()) + { + onItemSelected(index); + } + } + else if (arg.button == SDL_CONTROLLER_BUTTON_B) + { + onCloseButtonClicked(mCloseButton); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_X) + { + onTakeAllButtonClicked(mTakeButton); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER) + { + if (mDisposeCorpseButton->getVisible()) + onDisposeCorpseButtonClicked(mDisposeCorpseButton); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP || + arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN || + arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT || + arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT) + { + mItemView->onControllerButtonEvent(arg); + mUsingGamepadGuiCursor = false; + } + + return true; + } + + bool ContainerWindow::onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg) + { + if (arg.axis == SDL_CONTROLLER_AXIS_LEFTX || arg.axis == SDL_CONTROLLER_AXIS_LEFTY) + { + mUsingGamepadGuiCursor = true; + } + return false; + } } diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 555fa8e1ae..5d49b4c3ff 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -55,6 +55,7 @@ namespace MWGui void onItemSelected(int index); void onBackgroundSelected(); void dragItem(MyGUI::Widget* sender, int count); + void takeItem(MyGUI::Widget* sender, int count); void dropItem(); void onCloseButtonClicked(MyGUI::Widget* _sender); void onTakeAllButtonClicked(MyGUI::Widget* _sender); @@ -64,6 +65,10 @@ namespace MWGui bool onTakeItem(const ItemStack& item, int count); void onReferenceUnavailable() override; + + bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override; + bool onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg) override; + bool mUsingGamepadGuiCursor = false; }; } #endif // CONTAINER_H diff --git a/apps/openmw/mwgui/itemview.cpp b/apps/openmw/mwgui/itemview.cpp index ff05a8b2d6..e568da5900 100644 --- a/apps/openmw/mwgui/itemview.cpp +++ b/apps/openmw/mwgui/itemview.cpp @@ -7,6 +7,8 @@ #include #include +#include + #include "itemmodel.hpp" #include "itemwidget.hpp" @@ -46,13 +48,14 @@ namespace MWGui MyGUI::Widget* dragArea = mScrollView->getChildAt(0); int maxHeight = mScrollView->getHeight(); - int rows = maxHeight / 42; - rows = std::max(rows, 1); - bool showScrollbar = int(std::ceil(dragArea->getChildCount() / float(rows))) > mScrollView->getWidth() / 42; + mRows = maxHeight / 42; + mRows = std::max(mRows, 1); + mItemCount = dragArea->getChildCount(); + bool showScrollbar = int(std::ceil(mItemCount / float(mRows))) > mScrollView->getWidth() / 42; if (showScrollbar) maxHeight -= 18; - for (unsigned int i = 0; i < dragArea->getChildCount(); ++i) + for (unsigned int i = 0; i < mItemCount; ++i) { MyGUI::Widget* w = dragArea->getChildAt(i); @@ -60,7 +63,7 @@ namespace MWGui y += 42; - if (y > maxHeight - 42 && i < dragArea->getChildCount() - 1) + if (y > maxHeight - 42 && i < mItemCount - 1) { x += 42; y = 0; @@ -70,6 +73,13 @@ namespace MWGui MyGUI::IntSize size = MyGUI::IntSize(std::max(mScrollView->getSize().width, x), mScrollView->getSize().height); + if (Settings::gui().mControllerMenus) + { + if (mControllerFocus >= mItemCount) + mControllerFocus = mItemCount - 1; + updateControllerFocus(-1, mControllerFocus); + } + // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the // scrollbar is hidden mScrollView->setVisibleVScroll(false); @@ -122,6 +132,11 @@ namespace MWGui void ItemView::resetScrollBars() { mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); + if (Settings::gui().mControllerMenus) + { + updateControllerFocus(mControllerFocus, 0); + mControllerFocus = 0; + } } void ItemView::onSelectedItem(MyGUI::Widget* sender) @@ -165,4 +180,50 @@ namespace MWGui MyGUI::FactoryManager::getInstance().registerFactory("Widget"); } + void ItemView::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) + { + if (!mItemCount) + return; + + int prevFocus = mControllerFocus; + + if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP && mControllerFocus % mRows != 0) + mControllerFocus--; + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN && mControllerFocus % mRows != mRows - 1) + mControllerFocus++; + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT && mControllerFocus >= mRows) + mControllerFocus -= mRows; + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT && mControllerFocus + mRows < mItemCount) + mControllerFocus += mRows; + + if (mControllerFocus < 0) + mControllerFocus = 0; + else if (mControllerFocus >= mItemCount - 1) + mControllerFocus = mItemCount - 1; + + if (prevFocus != mControllerFocus) + updateControllerFocus(prevFocus, mControllerFocus); + } + + void ItemView::updateControllerFocus(int _prevFocus, int _newFocus) + { + if (!mItemCount) + return; + + MyGUI::Widget* dragArea = mScrollView->getChildAt(0); + + if (_prevFocus >= 0 && _prevFocus < mItemCount) + { + ItemWidget* prev = (ItemWidget *)dragArea->getChildAt(_prevFocus); + if (prev) + prev->setControllerFocus(false); + } + + if (_newFocus >= 0 && _newFocus < mItemCount) + { + ItemWidget* focused = (ItemWidget *)dragArea->getChildAt(_newFocus); + if (focused) + focused->setControllerFocus(true); + } + } } diff --git a/apps/openmw/mwgui/itemview.hpp b/apps/openmw/mwgui/itemview.hpp index cfbc8a37ac..8a53d3678e 100644 --- a/apps/openmw/mwgui/itemview.hpp +++ b/apps/openmw/mwgui/itemview.hpp @@ -2,6 +2,7 @@ #define MWGUI_ITEMVIEW_H #include +#include #include "itemmodel.hpp" @@ -31,6 +32,10 @@ namespace MWGui void resetScrollBars(); + int getControllerFocus() { return mControllerFocus; } + int getItemCount() { return mItemCount; } + void onControllerButtonEvent(const SDL_ControllerButtonEvent& arg); + private: void initialiseOverride() override; @@ -45,6 +50,11 @@ namespace MWGui std::unique_ptr mModel; MyGUI::ScrollView* mScrollView; + + int mItemCount = 0; + int mRows; + int mControllerFocus = 0; + void updateControllerFocus(int prevFocus, int newFocus); }; } diff --git a/apps/openmw/mwgui/itemwidget.cpp b/apps/openmw/mwgui/itemwidget.cpp index 05fff2d40f..5e47577b27 100644 --- a/apps/openmw/mwgui/itemwidget.cpp +++ b/apps/openmw/mwgui/itemwidget.cpp @@ -58,6 +58,7 @@ namespace MWGui : mItem(nullptr) , mItemShadow(nullptr) , mFrame(nullptr) + , mControllerBorder(nullptr) , mText(nullptr) { } @@ -82,10 +83,22 @@ namespace MWGui assignWidget(mText, "Text"); if (mText) mText->setNeedMouseFocus(false); + if (Settings::gui().mControllerMenus) + { + assignWidget(mControllerBorder, "ControllerBorder"); + if (mControllerBorder) + mControllerBorder->setNeedMouseFocus(false); + } Base::initialiseOverride(); } + void ItemWidget::setControllerFocus(bool focus) + { + if (mControllerBorder) + mControllerBorder->setVisible(focus); + } + void ItemWidget::setCount(int count) { if (!mText) diff --git a/apps/openmw/mwgui/itemwidget.hpp b/apps/openmw/mwgui/itemwidget.hpp index 63837ae92f..1191a23342 100644 --- a/apps/openmw/mwgui/itemwidget.hpp +++ b/apps/openmw/mwgui/itemwidget.hpp @@ -40,12 +40,15 @@ namespace MWGui void setIcon(const MWWorld::Ptr& ptr); void setFrame(const std::string& frame, const MyGUI::IntCoord& coord); + void setControllerFocus(bool focus); + protected: void initialiseOverride() override; MyGUI::ImageBox* mItem; MyGUI::ImageBox* mItemShadow; MyGUI::ImageBox* mFrame; + MyGUI::ImageBox* mControllerBorder; MyGUI::TextBox* mText; std::string mCurrentIcon; diff --git a/files/data/CMakeLists.txt b/files/data/CMakeLists.txt index d9218b45b2..0290519806 100644 --- a/files/data/CMakeLists.txt +++ b/files/data/CMakeLists.txt @@ -9,6 +9,7 @@ set(BUILTIN_DATA_FILES textures/omw_menu_scroll_right.dds textures/omw_menu_scroll_center_h.dds textures/omw_menu_scroll_center_v.dds + textures/omw_menu_icon_active.dds textures/omw/water_nm.png fonts/DejaVuFontLicense.txt diff --git a/files/data/mygui/openmw_resources.xml b/files/data/mygui/openmw_resources.xml index 4c32512004..08586ea75c 100644 --- a/files/data/mygui/openmw_resources.xml +++ b/files/data/mygui/openmw_resources.xml @@ -144,6 +144,10 @@ + + + + diff --git a/files/data/textures/omw_menu_icon_active.dds b/files/data/textures/omw_menu_icon_active.dds new file mode 100644 index 0000000000..be743ace7f Binary files /dev/null and b/files/data/textures/omw_menu_icon_active.dds differ