Add controller support to barter window

This commit is contained in:
Andrew Lanzone 2025-05-26 21:08:05 -07:00
parent 71fd8b8840
commit 14b0c9afbe
6 changed files with 127 additions and 5 deletions

View File

@ -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);

View File

@ -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<MyGUI::Widget*, int> EventHandle_WidgetInt;

View File

@ -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)
{

View File

@ -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));
}
}
}

View File

@ -168,6 +168,12 @@ namespace MWGui
std::numeric_limits<int>::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);
}
}

View File

@ -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);