diff --git a/apps/openmw/mwgui/countdialog.cpp b/apps/openmw/mwgui/countdialog.cpp index 75a2fc6034..d922b990cd 100644 --- a/apps/openmw/mwgui/countdialog.cpp +++ b/apps/openmw/mwgui/countdialog.cpp @@ -41,7 +41,7 @@ namespace MWGui MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); mSlider->setScrollRange(maxCount); - mItemText->setCaption(item); + mItemText->setCaptionWithReplacing(item); int width = std::max(mItemText->getTextSize().width + 160, 320); setCoord(viewSize.width / 2 - width / 2, viewSize.height / 2 - mMainWidget->getHeight() / 2, width, @@ -57,6 +57,13 @@ namespace MWGui mItemEdit->setValue(maxCount); } + void CountDialog::setCount(int count) + { + count = std::clamp(count, 1, (int)mSlider->getScrollRange()); + mSlider->setScrollPosition(count - 1); + mItemEdit->setValue(count); + } + void CountDialog::onCancelButtonClicked(MyGUI::Widget* _sender) { setVisible(false); diff --git a/apps/openmw/mwgui/countdialog.hpp b/apps/openmw/mwgui/countdialog.hpp index 695de09215..b3a1aab3b3 100644 --- a/apps/openmw/mwgui/countdialog.hpp +++ b/apps/openmw/mwgui/countdialog.hpp @@ -17,6 +17,7 @@ namespace MWGui public: CountDialog(); void openCountDialog(const std::string& item, const std::string& message, const int maxCount); + void setCount(int count); typedef MyGUI::delegates::MultiDelegate EventHandle_WidgetInt; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 7f314fed14..2e128f15f8 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -133,7 +133,6 @@ namespace MWGui if (Settings::gui().mControllerMenus) { mControllerButtons.b = "#{sBack}"; - mControllerButtons.r1 = "Filter"; mControllerButtons.r3 = "#{sInfo}"; } @@ -892,7 +891,7 @@ namespace MWGui break; case MWGui::GM_Barter: mControllerButtons.a = "#{sSell}"; - mControllerButtons.x = ""; + mControllerButtons.x = "#{sOffer}"; mControllerButtons.y = ""; mControllerButtons.r2 = "#{sBarter}"; break; @@ -959,6 +958,14 @@ namespace MWGui (MWGui::ContainerWindow *)MWBase::Environment::get().getWindowManager()->getGuiModeWindows(mGuiMode).at(0); containerWindow->onControllerButtonEvent(arg); } + else if (mGuiMode == MWGui::GM_Barter) + { + // Offer. Pass the button press to the barter window and let it do the logic + // of making an offer. + MWGui::TradeWindow* tradeWindow = + (MWGui::TradeWindow*)MWBase::Environment::get().getWindowManager()->getGuiModeWindows(mGuiMode).at(1); + tradeWindow->onControllerButtonEvent(arg); + } } else if (arg.button == SDL_CONTROLLER_BUTTON_Y) { diff --git a/apps/openmw/mwgui/itemview.cpp b/apps/openmw/mwgui/itemview.cpp index a223bde5e0..9cde52f0c2 100644 --- a/apps/openmw/mwgui/itemview.cpp +++ b/apps/openmw/mwgui/itemview.cpp @@ -52,12 +52,14 @@ namespace MWGui MyGUI::Widget* dragArea = mScrollView->getChildAt(0); int maxHeight = mScrollView->getHeight(); - mRows = maxHeight / 42; - mRows = std::max(mRows, 1); + mRows = std::max(maxHeight / 42, 1); mItemCount = dragArea->getChildCount(); bool showScrollbar = int(std::ceil(mItemCount / float(mRows))) > mScrollView->getWidth() / 42; if (showScrollbar) + { maxHeight -= 18; + mRows = std::max(maxHeight / 42, 1); + } for (unsigned int i = 0; i < mItemCount; ++i) { @@ -262,6 +264,13 @@ namespace MWGui focused->setControllerFocus(true); if (mControllerTooltip) MWBase::Environment::get().getInputManager()->warpMouseToWidget(focused); + + // Scroll the list to keep the active item in view + int column = newFocus / mRows; + if (column <= 3) + mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); + else + mScrollView->setViewOffset(MyGUI::IntPoint(-42 * (column - 3), 0)); } } } diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index ba752303d2..3e4b8732bb 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -168,6 +168,12 @@ namespace MWGui std::numeric_limits::min() + 1); // disallow INT_MIN since abs(INT_MIN) is undefined setCoord(400, 0, 400, 300); + + mControllerButtons.a = "#{sBuy}"; + mControllerButtons.b = "#{sBack}"; + mControllerButtons.x = "#{sOffer}"; + mControllerButtons.r3 = "#{sInfo}"; + mControllerButtons.l2 = "#{sInventory}"; } void TradeWindow::setPtr(const MWWorld::Ptr& actor) @@ -201,6 +207,10 @@ namespace MWGui onFilterChanged(mFilterAll); mFilterEdit->setCaption({}); + + // Cycle to the buy window if it's not active. + if (Settings::gui().mControllerMenus && !mActiveControllerWindow) + MWBase::Environment::get().getWindowManager()->cycleActiveControllerWindow(true); } void TradeWindow::onFrame(float dt) @@ -339,6 +349,13 @@ namespace MWGui } } + void TradeWindow::onOfferSubmitted(MyGUI::Widget* _sender, int offerAmount) + { + mCurrentBalance = mCurrentBalance < 0 ? -offerAmount : offerAmount; + updateLabels(); + onOfferButtonClicked(mOfferButton); + } + void TradeWindow::onOfferButtonClicked(MyGUI::Widget* _sender) { TradeItemModel* playerItemModel @@ -643,4 +660,81 @@ namespace MWGui if (mTradeModel && mTradeModel->usesContainer(ptr)) MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Barter); } + + bool TradeWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) + { + if (arg.button == SDL_CONTROLLER_BUTTON_A) + { + int index = mItemView->getControllerFocus(); + if (index >= 0 && index < mItemView->getItemCount()) + onItemSelected(index); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_B) + { + onCancelButtonClicked(mCancelButton); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_X) + { + if (mCurrentBalance == 0) + return true; + // Show a count dialog to allow for bartering. + CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); + if (mCurrentBalance < 0) + { + // Buying from the merchant + dialog->openCountDialog("#{sTotalcost}:", "#{sOffer}", -mCurrentMerchantOffer); + dialog->setCount(-mCurrentBalance); + } + else + { + // Selling to the merchant + dialog->openCountDialog("#{sTotalsold}:", "#{sOffer}", getMerchantGold()); + dialog->setCount(mCurrentBalance); + } + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &TradeWindow::onOfferSubmitted); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER) + { + if (mFilterAll->getStateSelected()) + onFilterChanged(mFilterMisc); + else if (mFilterWeapon->getStateSelected()) + onFilterChanged(mFilterAll); + else if (mFilterApparel->getStateSelected()) + onFilterChanged(mFilterWeapon); + else if (mFilterMagic->getStateSelected()) + onFilterChanged(mFilterApparel); + else if (mFilterMisc->getStateSelected()) + onFilterChanged(mFilterMagic); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) + { + if (mFilterAll->getStateSelected()) + onFilterChanged(mFilterWeapon); + else if (mFilterWeapon->getStateSelected()) + onFilterChanged(mFilterApparel); + else if (mFilterApparel->getStateSelected()) + onFilterChanged(mFilterMagic); + else if (mFilterMagic->getStateSelected()) + onFilterChanged(mFilterMisc); + else if (mFilterMisc->getStateSelected()) + onFilterChanged(mFilterAll); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSTICK || + 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.button); + } + + return true; + } + + void TradeWindow::setActiveControllerWindow(bool active) + { + mItemView->setActiveControllerWindow(active); + WindowBase::setActiveControllerWindow(active); + } } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 33c39cb269..afd271ed2f 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -47,6 +47,9 @@ namespace MWGui std::string_view getWindowIdForLua() const override { return "Trade"; } + bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override; + void setActiveControllerWindow(bool active) override; + private: ItemView* mItemView; SortFilterItemModel* mSortModel; @@ -102,6 +105,7 @@ namespace MWGui void onBalanceButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); void onBalanceValueChanged(int value); void onRepeatClick(MyGUI::Widget* widget, MyGUI::ControllerItem* controller); + void onOfferSubmitted(MyGUI::Widget* _sender, int offerAmount); void addRepeatController(MyGUI::Widget* widget);