mirror of
https://github.com/OpenMW/openmw.git
synced 2025-12-07 17:34:33 +00:00
Merge branch openmw:master into master
This commit is contained in:
commit
cf5eb9cd63
178 changed files with 5459 additions and 169 deletions
|
|
@ -75,6 +75,7 @@
|
|||
Feature #8580: Sort characters in the save loading menu
|
||||
Feature #8597: Lua: Add more built-in event handlers
|
||||
Feature #8629: Expose path grid data to Lua
|
||||
Feature #8654: Allow lua world.createRecord to create NPC records
|
||||
|
||||
0.49.0
|
||||
------
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ message(STATUS "Configuring OpenMW...")
|
|||
set(OPENMW_VERSION_MAJOR 0)
|
||||
set(OPENMW_VERSION_MINOR 50)
|
||||
set(OPENMW_VERSION_RELEASE 0)
|
||||
set(OPENMW_LUA_API_REVISION 87)
|
||||
set(OPENMW_LUA_API_REVISION 90)
|
||||
set(OPENMW_POSTPROCESSING_API_REVISION 3)
|
||||
|
||||
set(OPENMW_VERSION_COMMITHASH "")
|
||||
|
|
|
|||
|
|
@ -303,6 +303,9 @@ bool Launcher::SettingsPage::loadSettings()
|
|||
loadSettingBool(Settings::gui().mColorTopicEnable, *changeDialogTopicsCheckBox);
|
||||
showOwnedComboBox->setCurrentIndex(Settings::game().mShowOwned);
|
||||
loadSettingBool(Settings::gui().mStretchMenuBackground, *stretchBackgroundCheckBox);
|
||||
connect(controllerMenusCheckBox, &QCheckBox::toggled, this, &SettingsPage::slotControllerMenusToggled);
|
||||
loadSettingBool(Settings::gui().mControllerMenus, *controllerMenusCheckBox);
|
||||
loadSettingBool(Settings::gui().mControllerTooltips, *controllerMenuTooltipsCheckBox);
|
||||
loadSettingBool(Settings::map().mAllowZooming, *useZoomOnMapCheckBox);
|
||||
loadSettingBool(Settings::game().mGraphicHerbalism, *graphicHerbalismCheckBox);
|
||||
scalingSpinBox->setValue(Settings::gui().mScalingFactor);
|
||||
|
|
@ -496,6 +499,8 @@ void Launcher::SettingsPage::saveSettings()
|
|||
saveSettingBool(*changeDialogTopicsCheckBox, Settings::gui().mColorTopicEnable);
|
||||
saveSettingInt(*showOwnedComboBox, Settings::game().mShowOwned);
|
||||
saveSettingBool(*stretchBackgroundCheckBox, Settings::gui().mStretchMenuBackground);
|
||||
saveSettingBool(*controllerMenusCheckBox, Settings::gui().mControllerMenus);
|
||||
saveSettingBool(*controllerMenuTooltipsCheckBox, Settings::gui().mControllerTooltips);
|
||||
saveSettingBool(*useZoomOnMapCheckBox, Settings::map().mAllowZooming);
|
||||
saveSettingBool(*graphicHerbalismCheckBox, Settings::game().mGraphicHerbalism);
|
||||
Settings::gui().mScalingFactor.set(scalingSpinBox->value());
|
||||
|
|
@ -554,6 +559,11 @@ void Launcher::SettingsPage::slotAnimSourcesToggled(bool checked)
|
|||
}
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::slotControllerMenusToggled(bool checked)
|
||||
{
|
||||
controllerMenuTooltipsCheckBox->setEnabled(checked);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::slotPostProcessToggled(bool checked)
|
||||
{
|
||||
postprocessTransparentPostpassCheckBox->setEnabled(checked);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ namespace Launcher
|
|||
void slotSkyBlendingToggled(bool checked);
|
||||
void slotShadowDistLimitToggled(bool checked);
|
||||
void slotDistantLandToggled(bool checked);
|
||||
void slotControllerMenusToggled(bool checked);
|
||||
|
||||
private:
|
||||
Config::GameSettings& mGameSettings;
|
||||
|
|
|
|||
|
|
@ -1433,6 +1433,29 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QCheckBox" name="controllerMenusCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Make it easier to use game menus with a controller.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable Controller Menus</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QCheckBox" name="controllerMenuTooltipsCheckBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>When using controller menus, make tooltips visible by default.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Controller Tooltips By Default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="showOwnedLabel">
|
||||
<property name="text">
|
||||
|
|
|
|||
|
|
@ -291,8 +291,7 @@ int CSMDoc::WriteCellCollectionStage::setup()
|
|||
return mDocument.getData().getCells().getSize();
|
||||
}
|
||||
|
||||
void CSMDoc::WriteCellCollectionStage::writeReferences(
|
||||
const std::deque<int>& references, bool interior, unsigned int& newRefNum)
|
||||
void CSMDoc::WriteCellCollectionStage::writeReferences(const std::deque<int>& references, bool interior)
|
||||
{
|
||||
ESM::ESMWriter& writer = mState.getWriter();
|
||||
|
||||
|
|
@ -304,6 +303,8 @@ void CSMDoc::WriteCellCollectionStage::writeReferences(
|
|||
{
|
||||
CSMWorld::CellRef refRecord = ref.get();
|
||||
|
||||
const bool isLocal = refRecord.mRefNum.mContentFile == -1;
|
||||
|
||||
// -1 is the current file, saved indices are 1-based
|
||||
refRecord.mRefNum.mContentFile++;
|
||||
|
||||
|
|
@ -316,12 +317,7 @@ void CSMDoc::WriteCellCollectionStage::writeReferences(
|
|||
}
|
||||
|
||||
ESM::RefId streamId = ESM::RefId::stringRefId(stream.str());
|
||||
if (refRecord.mNew || refRecord.mRefNum.mIndex == 0
|
||||
|| (!interior && ref.mState == CSMWorld::RecordBase::State_ModifiedOnly && refRecord.mCell != streamId))
|
||||
{
|
||||
refRecord.mRefNum.mIndex = newRefNum++;
|
||||
}
|
||||
else if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell) != streamId
|
||||
if (!isLocal && (refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell) != streamId
|
||||
&& !interior)
|
||||
{
|
||||
// An empty mOriginalCell is meant to indicate that it is the same as
|
||||
|
|
@ -362,9 +358,6 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages)
|
|||
CSMWorld::Cell cellRecord = cell.get();
|
||||
const bool interior = !cellRecord.mId.startsWith("#");
|
||||
|
||||
// count new references and adjust RefNumCount accordingsly
|
||||
unsigned int newRefNum = cellRecord.mRefNumCounter;
|
||||
|
||||
if (references != nullptr)
|
||||
{
|
||||
for (std::deque<int>::const_iterator iter(references->begin()); iter != references->end(); ++iter)
|
||||
|
|
@ -390,9 +383,6 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages)
|
|||
ESM::RefId::stringRefId(CSMWorld::CellCoordinates(refRecord.getCellIndex()).getId(""))
|
||||
!= refRecord.mCell))
|
||||
++cellRecord.mRefNumCounter;
|
||||
|
||||
if (refRecord.mRefNum.mIndex >= newRefNum)
|
||||
newRefNum = refRecord.mRefNum.mIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -415,9 +405,9 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages)
|
|||
// write references
|
||||
if (references != nullptr)
|
||||
{
|
||||
writeReferences(persistentRefs, interior, newRefNum);
|
||||
writeReferences(persistentRefs, interior);
|
||||
cellRecord.saveTempMarker(writer, static_cast<int>(references->size()) - persistentRefs.size());
|
||||
writeReferences(tempRefs, interior, newRefNum);
|
||||
writeReferences(tempRefs, interior);
|
||||
}
|
||||
|
||||
writer.endRecord(cellRecord.sRecordId);
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ namespace CSMDoc
|
|||
Document& mDocument;
|
||||
SavingState& mState;
|
||||
|
||||
void writeReferences(const std::deque<int>& references, bool interior, unsigned int& newRefNum);
|
||||
void writeReferences(const std::deque<int>& references, bool interior);
|
||||
|
||||
public:
|
||||
WriteCellCollectionStage(Document& document, SavingState& state);
|
||||
|
|
|
|||
|
|
@ -273,15 +273,6 @@ namespace CSMWorld
|
|||
copy->mState = RecordBase::State_ModifiedOnly;
|
||||
setRecordId(destination, copy->get());
|
||||
|
||||
if constexpr (std::is_same_v<ESXRecordT, CSMWorld::CellRef>)
|
||||
{
|
||||
if (type == UniversalId::Type_Reference)
|
||||
{
|
||||
CSMWorld::CellRef* ptr = (CSMWorld::CellRef*)©->mModified;
|
||||
ptr->mRefNum.mIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (std::is_same_v<ESXRecordT, ESM::Dialogue>)
|
||||
{
|
||||
copy->mModified.mStringId = copy->mModified.mId.getRefIdString();
|
||||
|
|
|
|||
|
|
@ -175,6 +175,9 @@ void CSMWorld::RefCollection::load(ESM::ESMReader& reader, int cellIndex, bool b
|
|||
ref.mIdNum = mNextId; // FIXME: fragile
|
||||
ref.mId = ESM::RefId::stringRefId(getNewId());
|
||||
|
||||
if (!base && ref.mRefNum.mIndex > mHighestUsedRefNum)
|
||||
mHighestUsedRefNum = ref.mRefNum.mIndex;
|
||||
|
||||
cache.emplace(ref.mRefNum, ref.mIdNum);
|
||||
|
||||
auto record = std::make_unique<Record<CellRef>>();
|
||||
|
|
@ -222,6 +225,11 @@ std::string CSMWorld::RefCollection::getNewId()
|
|||
return "ref#" + std::to_string(mNextId++);
|
||||
}
|
||||
|
||||
uint32_t CSMWorld::RefCollection::getNextRefNum()
|
||||
{
|
||||
return ++mHighestUsedRefNum;
|
||||
}
|
||||
|
||||
unsigned int CSMWorld::RefCollection::extractIdNum(std::string_view id) const
|
||||
{
|
||||
std::string::size_type separator = id.find_last_of('#');
|
||||
|
|
@ -283,6 +291,7 @@ void CSMWorld::RefCollection::appendBlankRecord(const ESM::RefId& id, UniversalI
|
|||
|
||||
record->get().mId = id;
|
||||
record->get().mIdNum = extractIdNum(id.getRefIdString());
|
||||
record->get().mRefNum.mIndex = getNextRefNum();
|
||||
|
||||
Collection<CellRef>::appendRecord(std::move(record));
|
||||
}
|
||||
|
|
@ -298,15 +307,13 @@ void CSMWorld::RefCollection::cloneRecord(
|
|||
|
||||
copy->get().mId = destination;
|
||||
copy->get().mIdNum = extractIdNum(destination.getRefIdString());
|
||||
copy->get().mRefNum.mIndex = getNextRefNum();
|
||||
|
||||
if (copy->get().mRefNum.hasContentFile())
|
||||
{
|
||||
mRefIndex.insert(std::make_pair(static_cast<Record<CellRef>*>(copy.get())->get().mIdNum, index));
|
||||
copy->get().mRefNum.mContentFile = -1;
|
||||
copy->get().mRefNum.mIndex = index;
|
||||
}
|
||||
else
|
||||
copy->get().mRefNum.mIndex = copy->get().mIdNum;
|
||||
|
||||
insertRecord(std::move(copy), getAppendIndex(destination, type)); // call RefCollection::insertRecord()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef CSM_WOLRD_REFCOLLECTION_H
|
||||
#define CSM_WOLRD_REFCOLLECTION_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
|
@ -40,9 +41,12 @@ namespace CSMWorld
|
|||
std::map<unsigned int, int> mRefIndex; // CellRef index keyed by CSMWorld::CellRef::mIdNum
|
||||
|
||||
int mNextId;
|
||||
uint32_t mHighestUsedRefNum = 0;
|
||||
|
||||
unsigned int extractIdNum(std::string_view id) const;
|
||||
|
||||
uint32_t getNextRefNum();
|
||||
|
||||
int getIntIndex(unsigned int id) const;
|
||||
|
||||
int searchId(unsigned int id) const;
|
||||
|
|
|
|||
|
|
@ -1277,9 +1277,8 @@ void CSVRender::InstanceMode::cloneSelectedInstances()
|
|||
if (CSVRender::ObjectTag* objectTag = dynamic_cast<CSVRender::ObjectTag*>(tag.get()))
|
||||
{
|
||||
macro.push(new CSMWorld::CloneCommand(referencesTable, objectTag->mObject->getReferenceId(),
|
||||
"ref#" + std::to_string(referencesTable.rowCount()), CSMWorld::UniversalId::Type_Reference));
|
||||
document.getData().getReferences().getNewId(), CSMWorld::UniversalId::Type_Reference));
|
||||
}
|
||||
// getWorldspaceWidget().clearSelection(Mask_Reference);
|
||||
}
|
||||
|
||||
void CSVRender::InstanceMode::dropInstance(CSVRender::Object* object, float dropHeight)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ add_openmw_dir (mwgui
|
|||
tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog
|
||||
recharge mode videowidget backgroundimage itemwidget screenfader debugwindow spellmodel spellview
|
||||
draganddrop timeadvancer jailscreen itemchargeview keyboardnavigation textcolours statswatcher
|
||||
postprocessorhud settings worlditemmodel itemtransfer
|
||||
postprocessorhud settings worlditemmodel itemtransfer controllerbuttonsoverlay inventorytabsoverlay
|
||||
)
|
||||
|
||||
add_openmw_dir (mwdialogue
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@ namespace ESM
|
|||
class ESMWriter;
|
||||
}
|
||||
|
||||
namespace MyGUI
|
||||
{
|
||||
class Widget;
|
||||
}
|
||||
|
||||
namespace MWBase
|
||||
{
|
||||
/// \brief Interface for input manager (implemented in MWInput)
|
||||
|
|
@ -61,6 +66,7 @@ namespace MWBase
|
|||
virtual float getControllerAxisValue(SDL_GameControllerAxis axis) const = 0; // returns value in range [-1, 1]
|
||||
virtual int getMouseMoveX() const = 0;
|
||||
virtual int getMouseMoveY() const = 0;
|
||||
virtual void warpMouseToWidget(MyGUI::Widget* widget) = 0;
|
||||
|
||||
/// Actions available for binding to keyboard buttons
|
||||
virtual const std::initializer_list<int>& getActionKeySorting() = 0;
|
||||
|
|
@ -77,6 +83,8 @@ namespace MWBase
|
|||
/// @return true if joystick, false otherwise
|
||||
virtual bool joystickLastUsed() = 0;
|
||||
virtual void setJoystickLastUsed(bool enabled) = 0;
|
||||
virtual std::string getControllerButtonIcon(int button) = 0;
|
||||
virtual std::string getControllerAxisIcon(int axis) = 0;
|
||||
|
||||
virtual int countSavedGameRecords() const = 0;
|
||||
virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress) = 0;
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ namespace MWGui
|
|||
class MessageBox;
|
||||
class PostProcessorHud;
|
||||
class SettingsWindow;
|
||||
class HUD;
|
||||
class WindowBase;
|
||||
|
||||
enum ShowInDialogueMode
|
||||
{
|
||||
|
|
@ -157,7 +159,9 @@ namespace MWBase
|
|||
virtual MWGui::CountDialog* getCountDialog() = 0;
|
||||
virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0;
|
||||
virtual MWGui::TradeWindow* getTradeWindow() = 0;
|
||||
virtual MWGui::HUD* getHud() = 0;
|
||||
virtual MWGui::PostProcessorHud* getPostProcessorHud() = 0;
|
||||
virtual std::vector<MWGui::WindowBase*> getGuiModeWindows(MWGui::GuiMode mode) = 0;
|
||||
|
||||
/// Make the player use an item, while updating GUI state accordingly
|
||||
virtual void useItem(const MWWorld::Ptr& item, bool force = false) = 0;
|
||||
|
|
@ -381,6 +385,17 @@ namespace MWBase
|
|||
/// Same as viewer->getCamera()->getCullMask(), provided for consistency.
|
||||
virtual uint32_t getCullMask() = 0;
|
||||
|
||||
/// Return the window that should receive controller events
|
||||
virtual MWGui::WindowBase* getActiveControllerWindow() = 0;
|
||||
/// Return the available height for menus accounting for visible controller overlays
|
||||
virtual int getControllerMenuHeight() = 0;
|
||||
/// Cycle to the next window to receive controller events
|
||||
virtual void cycleActiveControllerWindow(bool next) = 0;
|
||||
virtual void setActiveControllerWindow(MWGui::GuiMode mode, int activeIndex) = 0;
|
||||
virtual bool getControllerTooltip() const = 0;
|
||||
virtual void setControllerTooltip(bool enabled) = 0;
|
||||
virtual void updateControllerButtonsOverlay() = 0;
|
||||
|
||||
// Used in Lua bindings
|
||||
virtual const std::vector<MWGui::GuiMode>& getGuiModeStack() const = 0;
|
||||
virtual void setDisabledByLua(std::string_view windowId, bool disabled) = 0;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <MyGUI_ControllerRepeatClick.h>
|
||||
#include <MyGUI_EditBox.h>
|
||||
#include <MyGUI_Gui.h>
|
||||
#include <MyGUI_InputManager.h>
|
||||
#include <MyGUI_UString.h>
|
||||
|
||||
#include <components/esm3/loadappa.hpp>
|
||||
|
|
@ -91,6 +92,15 @@ namespace MWGui
|
|||
mFilterValue->eventEditTextChange += MyGUI::newDelegate(this, &AlchemyWindow::onFilterEdited);
|
||||
mFilterType->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::switchFilterType);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
mControllerButtons.mX = "#{sCreate}";
|
||||
mControllerButtons.mY = "#{sMagicEffects}";
|
||||
mControllerButtons.mR3 = "#{sInfo}";
|
||||
}
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
|
|
@ -165,7 +175,12 @@ namespace MWGui
|
|||
std::string_view ingredient = wm->getGameSettingString("sIngredients", "Ingredients");
|
||||
|
||||
if (mFilterType->getCaption() == ingredient)
|
||||
mCurrentFilter = FilterType::ByName;
|
||||
{
|
||||
if (Settings::gui().mControllerMenus)
|
||||
switchFilterType(mFilterType);
|
||||
else
|
||||
mCurrentFilter = FilterType::ByName;
|
||||
}
|
||||
else
|
||||
mCurrentFilter = FilterType::ByEffect;
|
||||
updateFilters();
|
||||
|
|
@ -291,6 +306,9 @@ namespace MWGui
|
|||
initFilter();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNameEdit);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
mItemView->setActiveControllerWindow(true);
|
||||
}
|
||||
|
||||
void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender)
|
||||
|
|
@ -528,4 +546,86 @@ namespace MWGui
|
|||
if (currentCount > 1)
|
||||
mBrewCountEdit->setValue(currentCount - 1);
|
||||
}
|
||||
|
||||
void AlchemyWindow::filterListButtonHandler(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A || arg.button == SDL_CONTROLLER_BUTTON_Y)
|
||||
{
|
||||
// Select the highlighted entry in the combo box and close it. List is closed by focusing on another
|
||||
// widget.
|
||||
size_t index = mFilterValue->getIndexSelected();
|
||||
mFilterValue->setIndexSelected(index);
|
||||
onFilterChanged(mFilterValue, index);
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNameEdit);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
// Close the list without selecting anything. List is closed by focusing on another widget.
|
||||
mFilterValue->clearIndexSelected();
|
||||
onFilterEdited(mFilterValue);
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNameEdit);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::ArrowUp, 0, false);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::ArrowDown, 0, false);
|
||||
}
|
||||
|
||||
bool AlchemyWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||
bool isFilterListOpen
|
||||
= focus != nullptr && focus->getParent() != nullptr && focus->getParent()->getParent() == mFilterValue;
|
||||
|
||||
if (isFilterListOpen)
|
||||
{
|
||||
// When the filter list combo box is open, send all inputs to it.
|
||||
filterListButtonHandler(arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
// Remove active ingredients or close the window, starting with right-most slot.
|
||||
for (int i = mIngredients.size() - 1; i >= 0; --i)
|
||||
{
|
||||
if (mIngredients[i]->isUserString("ToolTipType"))
|
||||
{
|
||||
onIngredientSelected(mIngredients[i]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// If the ingredients list is empty, B closes the menu.
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
onCreateButtonClicked(mCreateButton);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_Y && mFilterValue->getItemCount() > 0)
|
||||
{
|
||||
// Magical effects/ingredients filter
|
||||
if (mFilterValue->getIndexSelected() != MyGUI::ITEM_NONE)
|
||||
{
|
||||
// Clear the active filter
|
||||
mFilterValue->clearIndexSelected();
|
||||
onFilterEdited(mFilterValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Open the combo box to choose the a filter
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mFilterValue);
|
||||
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::ArrowDown, 0, false);
|
||||
}
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
|
||||
onDecreaseButtonTriggered();
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
|
||||
onIncreaseButtonTriggered();
|
||||
else
|
||||
mItemView->onControllerButton(arg.button);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,6 +99,9 @@ namespace MWGui
|
|||
|
||||
std::vector<ItemWidget*> mApparatus;
|
||||
std::vector<ItemWidget*> mIngredients;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
void filterListButtonHandler(const SDL_ControllerButtonEvent& arg);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,15 +50,20 @@ namespace MWGui
|
|||
mBirthList->eventListSelectAccept += MyGUI::newDelegate(this, &BirthDialog::onAccept);
|
||||
mBirthList->eventListChangePosition += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
||||
|
||||
MyGUI::Button* backButton;
|
||||
getWidget(backButton, "BackButton");
|
||||
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked);
|
||||
getWidget(mBackButton, "BackButton");
|
||||
mBackButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked);
|
||||
|
||||
MyGUI::Button* okButton;
|
||||
getWidget(okButton, "OKButton");
|
||||
okButton->setCaption(
|
||||
getWidget(mOkButton, "OKButton");
|
||||
mOkButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {})));
|
||||
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked);
|
||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerButtons.mLStick = "#{sMouse}";
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{sBack}";
|
||||
}
|
||||
|
||||
updateBirths();
|
||||
updateSpells();
|
||||
|
|
@ -70,8 +75,17 @@ namespace MWGui
|
|||
getWidget(okButton, "OKButton");
|
||||
|
||||
if (shown)
|
||||
{
|
||||
okButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", {})));
|
||||
mControllerButtons.mX = "#{sNext}";
|
||||
}
|
||||
else if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
okButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sDone", {})));
|
||||
mControllerButtons.mX = "#{sDone}";
|
||||
}
|
||||
else
|
||||
okButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {})));
|
||||
|
|
@ -271,4 +285,30 @@ namespace MWGui
|
|||
mSpellArea->setVisibleVScroll(true);
|
||||
mSpellArea->setViewOffset(MyGUI::IntPoint(0, 0));
|
||||
}
|
||||
|
||||
bool BirthDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onBackClicked(mBackButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
{
|
||||
onOkClicked(mOkButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
winMgr->setKeyFocusWidget(mBirthList);
|
||||
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowUp, 0, false);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
winMgr->setKeyFocusWidget(mBirthList);
|
||||
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowDown, 0, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,8 +53,12 @@ namespace MWGui
|
|||
MyGUI::ScrollView* mSpellArea;
|
||||
MyGUI::ImageBox* mBirthImage;
|
||||
std::vector<MyGUI::Widget*> mSpellItems;
|
||||
MyGUI::Button* mBackButton;
|
||||
MyGUI::Button* mOkButton;
|
||||
|
||||
ESM::RefId mCurrentBirthId;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -105,6 +105,18 @@ namespace MWGui
|
|||
Styles mStyles;
|
||||
MyGUI::IntRect mRect;
|
||||
|
||||
void setColour(size_t section, size_t line, size_t run, const MyGUI::Colour& colour) const override
|
||||
{
|
||||
if (section >= mSections.size())
|
||||
return;
|
||||
if (line >= mSections[section].mLines.size())
|
||||
return;
|
||||
if (run >= mSections[section].mLines[line].mRuns.size())
|
||||
return;
|
||||
|
||||
mSections[section].mLines[line].mRuns[run].mStyle->mNormalColour = colour;
|
||||
}
|
||||
|
||||
virtual ~TypesetBookImpl() {}
|
||||
|
||||
Range addContent(const BookTypesetter::Utf8Span& text)
|
||||
|
|
@ -1288,6 +1300,12 @@ namespace MWGui
|
|||
|
||||
void unadviseLinkClicked() override { mPageDisplay->mLinkClicked = std::function<void(InteractiveId)>(); }
|
||||
|
||||
void setFocusItem(BookTypesetter::Style* itemStyle) override
|
||||
{
|
||||
mPageDisplay->mFocusItem = static_cast<TypesetBookImpl::StyleImpl*>(itemStyle);
|
||||
mPageDisplay->dirtyFocusItem();
|
||||
}
|
||||
|
||||
protected:
|
||||
void initialiseOverride() override
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ namespace MWGui
|
|||
/// text combined prior to pagination.
|
||||
virtual std::pair<unsigned int, unsigned int> getSize() const = 0;
|
||||
|
||||
/// Used to highlight journal indices
|
||||
virtual void setColour(size_t section, size_t line, size_t run, const MyGUI::Colour& colour) const = 0;
|
||||
|
||||
virtual ~TypesetBook() = default;
|
||||
};
|
||||
|
||||
|
|
@ -164,6 +167,8 @@ namespace MWGui
|
|||
/// Register the widget and associated sub-widget with MyGUI. Should be
|
||||
/// called once near the beginning of the program.
|
||||
static void registerMyGUIComponents();
|
||||
|
||||
virtual void setFocusItem(BookTypesetter::Style* itemStyle) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,10 @@ namespace MWGui
|
|||
MyGUI::IntCoord(0, 0, (64 - 7) * scale, mNextPageButton->getSize().height * scale));
|
||||
}
|
||||
|
||||
mControllerButtons.mL1 = "#{sPrev}";
|
||||
mControllerButtons.mR1 = "#{sNext}";
|
||||
mControllerButtons.mB = "#{Interface:Close}";
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
|
|
@ -218,4 +222,26 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
ControllerButtons* BookWindow::getControllerButtons()
|
||||
{
|
||||
mControllerButtons.mA = mTakeButton->getVisible() ? "#{sTake}" : "";
|
||||
return &mControllerButtons;
|
||||
}
|
||||
|
||||
bool BookWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mTakeButton->getVisible())
|
||||
onTakeButtonClicked(mTakeButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
onCloseButtonClicked(mCloseButton);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
|
||||
prevPage();
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
|
||||
nextPage();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,10 @@ namespace MWGui
|
|||
void setInventoryAllowed(bool allowed);
|
||||
|
||||
void onResChange(int, int) override { center(); }
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
|
||||
std::string_view getWindowIdForLua() const override { return "Book"; }
|
||||
ControllerButtons* getControllerButtons() override;
|
||||
|
||||
protected:
|
||||
void onNextPageButtonClicked(MyGUI::Widget* sender);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <components/esm3/loadnpc.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
#include <components/settings/values.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
|
||||
#include "tooltips.hpp"
|
||||
|
|
@ -46,15 +47,21 @@ namespace MWGui
|
|||
getWidget(mClassImage, "ClassImage");
|
||||
getWidget(mClassName, "ClassName");
|
||||
|
||||
MyGUI::Button* backButton;
|
||||
getWidget(backButton, "BackButton");
|
||||
backButton->setCaptionWithReplacing("#{sMessageQuestionAnswer3}");
|
||||
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onBackClicked);
|
||||
getWidget(mBackButton, "BackButton");
|
||||
mBackButton->setCaptionWithReplacing("#{sMessageQuestionAnswer3}");
|
||||
mBackButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onBackClicked);
|
||||
|
||||
MyGUI::Button* okButton;
|
||||
getWidget(okButton, "OKButton");
|
||||
okButton->setCaptionWithReplacing("#{sMessageQuestionAnswer2}");
|
||||
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked);
|
||||
getWidget(mOkButton, "OKButton");
|
||||
mOkButton->setCaptionWithReplacing("#{sMessageQuestionAnswer2}");
|
||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mOkButton->setStateSelected(true);
|
||||
mDisableGamepadCursor = true;
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{sBack}";
|
||||
}
|
||||
|
||||
center();
|
||||
}
|
||||
|
|
@ -71,6 +78,30 @@ namespace MWGui
|
|||
center();
|
||||
}
|
||||
|
||||
bool GenerateClassResultDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mOkButtonFocus)
|
||||
onOkClicked(mOkButton);
|
||||
else
|
||||
onBackClicked(mBackButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onBackClicked(mBackButton);
|
||||
}
|
||||
else if ((arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT && mOkButtonFocus)
|
||||
|| (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT && !mOkButtonFocus))
|
||||
{
|
||||
mOkButtonFocus = !mOkButtonFocus;
|
||||
mOkButton->setStateSelected(mOkButtonFocus);
|
||||
mBackButton->setStateSelected(!mOkButtonFocus);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// widget controls
|
||||
|
||||
void GenerateClassResultDialog::onOkClicked(MyGUI::Widget* _sender)
|
||||
|
|
@ -110,13 +141,18 @@ namespace MWGui
|
|||
|
||||
getWidget(mClassImage, "ClassImage");
|
||||
|
||||
MyGUI::Button* backButton;
|
||||
getWidget(backButton, "BackButton");
|
||||
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onBackClicked);
|
||||
getWidget(mBackButton, "BackButton");
|
||||
mBackButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onBackClicked);
|
||||
|
||||
MyGUI::Button* okButton;
|
||||
getWidget(okButton, "OKButton");
|
||||
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onOkClicked);
|
||||
getWidget(mOkButton, "OKButton");
|
||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onOkClicked);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerButtons.mLStick = "#{sMouse}";
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{sBack}";
|
||||
}
|
||||
|
||||
updateClasses();
|
||||
updateStats();
|
||||
|
|
@ -128,8 +164,17 @@ namespace MWGui
|
|||
getWidget(okButton, "OKButton");
|
||||
|
||||
if (shown)
|
||||
{
|
||||
okButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", {})));
|
||||
mControllerButtons.mX = "#{sNext}";
|
||||
}
|
||||
else if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
okButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sDone", {})));
|
||||
mControllerButtons.mX = "#{sDone}";
|
||||
}
|
||||
else
|
||||
okButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {})));
|
||||
|
|
@ -278,6 +323,32 @@ namespace MWGui
|
|||
setClassImage(mClassImage, mCurrentClassId);
|
||||
}
|
||||
|
||||
bool PickClassDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onBackClicked(mBackButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
{
|
||||
onOkClicked(mOkButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
winMgr->setKeyFocusWidget(mClassList);
|
||||
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowUp, 0, false);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
winMgr->setKeyFocusWidget(mClassList);
|
||||
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowDown, 0, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* InfoBoxDialog */
|
||||
|
||||
void InfoBoxDialog::fitToText(MyGUI::TextBox* widget)
|
||||
|
|
@ -312,6 +383,7 @@ namespace MWGui
|
|||
|
||||
InfoBoxDialog::InfoBoxDialog()
|
||||
: WindowModal("openmw_infobox.layout")
|
||||
, mControllerFocus(0)
|
||||
{
|
||||
getWidget(mTextBox, "TextBox");
|
||||
getWidget(mText, "Text");
|
||||
|
|
@ -319,6 +391,9 @@ namespace MWGui
|
|||
getWidget(mButtonBar, "ButtonBar");
|
||||
|
||||
center();
|
||||
|
||||
mDisableGamepadCursor = Settings::gui().mControllerMenus;
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
}
|
||||
|
||||
void InfoBoxDialog::setText(const std::string& str)
|
||||
|
|
@ -353,6 +428,13 @@ namespace MWGui
|
|||
fitToText(button);
|
||||
button->eventMouseButtonClick += MyGUI::newDelegate(this, &InfoBoxDialog::onButtonClicked);
|
||||
coord.top += button->getHeight();
|
||||
|
||||
if (Settings::gui().mControllerMenus && buttons.size() > 1 && this->mButtons.empty())
|
||||
{
|
||||
// First button is selected by default
|
||||
button->setStateSelected(true);
|
||||
}
|
||||
|
||||
this->mButtons.push_back(button);
|
||||
}
|
||||
}
|
||||
|
|
@ -382,6 +464,44 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
bool InfoBoxDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mControllerFocus < mButtons.size())
|
||||
onButtonClicked(mButtons[mControllerFocus]);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
if (mButtons.size() == 1)
|
||||
onButtonClicked(mButtons[0]);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
if (mButtons.size() <= 1)
|
||||
return true;
|
||||
if (mButtons.size() == 2 && mControllerFocus == 0)
|
||||
return true;
|
||||
|
||||
setControllerFocus(mButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus - 1, mButtons.size());
|
||||
setControllerFocus(mButtons, mControllerFocus, true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
if (mButtons.size() <= 1)
|
||||
return true;
|
||||
if (mButtons.size() == 2 && mControllerFocus == 1)
|
||||
return true;
|
||||
|
||||
setControllerFocus(mButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus + 1, mButtons.size());
|
||||
setControllerFocus(mButtons, mControllerFocus, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ClassChoiceDialog */
|
||||
|
||||
ClassChoiceDialog::ClassChoiceDialog()
|
||||
|
|
@ -405,6 +525,7 @@ namespace MWGui
|
|||
: WindowModal("openmw_chargen_create_class.layout")
|
||||
, mAffectedAttribute(nullptr)
|
||||
, mAffectedSkill(nullptr)
|
||||
, mControllerFocus(2)
|
||||
{
|
||||
// Centre dialog
|
||||
center();
|
||||
|
|
@ -450,14 +571,25 @@ namespace MWGui
|
|||
MyGUI::Button* descriptionButton;
|
||||
getWidget(descriptionButton, "DescriptionButton");
|
||||
descriptionButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionClicked);
|
||||
mButtons.push_back(descriptionButton);
|
||||
|
||||
MyGUI::Button* backButton;
|
||||
getWidget(backButton, "BackButton");
|
||||
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onBackClicked);
|
||||
mButtons.push_back(backButton);
|
||||
|
||||
MyGUI::Button* okButton;
|
||||
getWidget(okButton, "OKButton");
|
||||
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onOkClicked);
|
||||
mButtons.push_back(okButton);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
okButton->setStateSelected(true);
|
||||
mControllerButtons.mLStick = "#{sMouse}";
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{sBack}";
|
||||
}
|
||||
|
||||
// Set default skills, attributes
|
||||
|
||||
|
|
@ -545,13 +677,56 @@ namespace MWGui
|
|||
getWidget(okButton, "OKButton");
|
||||
|
||||
if (shown)
|
||||
{
|
||||
okButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", {})));
|
||||
mControllerButtons.mX = "#{sNext}";
|
||||
}
|
||||
else if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
okButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sDone", {})));
|
||||
mControllerButtons.mX = "#{sDone}";
|
||||
}
|
||||
else
|
||||
okButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {})));
|
||||
}
|
||||
|
||||
bool CreateClassDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mControllerFocus == 0)
|
||||
onDescriptionClicked(mButtons[0]);
|
||||
else if (mControllerFocus == 1)
|
||||
onBackClicked(mButtons[1]);
|
||||
else
|
||||
onOkClicked(mButtons[2]);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onBackClicked(mButtons[1]);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
{
|
||||
onOkClicked(mButtons[2]);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
|
||||
{
|
||||
setControllerFocus(mButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus - 1, mButtons.size());
|
||||
setControllerFocus(mButtons, mControllerFocus, true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
|
||||
{
|
||||
setControllerFocus(mButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus + 1, mButtons.size());
|
||||
setControllerFocus(mButtons, mControllerFocus, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// widget controls
|
||||
|
||||
void CreateClassDialog::onDialogCancel()
|
||||
|
|
@ -708,6 +883,9 @@ namespace MWGui
|
|||
MyGUI::Button* cancelButton;
|
||||
getWidget(cancelButton, "CancelButton");
|
||||
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked);
|
||||
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
}
|
||||
|
||||
SelectSpecializationDialog::~SelectSpecializationDialog() {}
|
||||
|
|
@ -739,6 +917,16 @@ namespace MWGui
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SelectSpecializationDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onCancelClicked(nullptr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* SelectAttributeDialog */
|
||||
|
||||
SelectAttributeDialog::SelectAttributeDialog()
|
||||
|
|
@ -760,6 +948,7 @@ namespace MWGui
|
|||
widget->setAttributeId(attribute.mId);
|
||||
widget->eventClicked += MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked);
|
||||
ToolTips::createAttributeToolTip(widget, attribute.mId);
|
||||
mAttributeButtons.emplace_back(widget);
|
||||
}
|
||||
|
||||
attributes->setVisibleVScroll(false);
|
||||
|
|
@ -770,6 +959,16 @@ namespace MWGui
|
|||
MyGUI::Button* cancelButton;
|
||||
getWidget(cancelButton, "CancelButton");
|
||||
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerFocus = 0;
|
||||
if (mAttributeButtons.size() > 0)
|
||||
mAttributeButtons[0]->setStateSelected(true);
|
||||
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
}
|
||||
}
|
||||
|
||||
// widget controls
|
||||
|
|
@ -791,6 +990,33 @@ namespace MWGui
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SelectAttributeDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mControllerFocus < mAttributeButtons.size())
|
||||
onAttributeClicked(mAttributeButtons[mControllerFocus]);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onCancelClicked(nullptr);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
mAttributeButtons[mControllerFocus]->setStateSelected(false);
|
||||
mControllerFocus = wrap(mControllerFocus - 1, mAttributeButtons.size());
|
||||
mAttributeButtons[mControllerFocus]->setStateSelected(true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
mAttributeButtons[mControllerFocus]->setStateSelected(false);
|
||||
mControllerFocus = wrap(mControllerFocus + 1, mAttributeButtons.size());
|
||||
mAttributeButtons[mControllerFocus]->setStateSelected(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* SelectSkillDialog */
|
||||
|
||||
SelectSkillDialog::SelectSkillDialog()
|
||||
|
|
@ -820,6 +1046,8 @@ namespace MWGui
|
|||
skillWidget->setSkillId(skill.mId);
|
||||
skillWidget->eventClicked += MyGUI::newDelegate(this, &SelectSkillDialog::onSkillClicked);
|
||||
ToolTips::createSkillToolTip(skillWidget, skill.mId);
|
||||
mSkillButtons.emplace_back(skillWidget);
|
||||
mNumSkillsPerSpecialization[skill.mData.mSpecialization]++;
|
||||
}
|
||||
for (const auto& [widget, coord] : specializations)
|
||||
{
|
||||
|
|
@ -832,6 +1060,16 @@ namespace MWGui
|
|||
MyGUI::Button* cancelButton;
|
||||
getWidget(cancelButton, "CancelButton");
|
||||
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerFocus = 0;
|
||||
if (mSkillButtons.size() > 0)
|
||||
mSkillButtons[0]->setStateSelected(true);
|
||||
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
}
|
||||
}
|
||||
|
||||
SelectSkillDialog::~SelectSkillDialog() {}
|
||||
|
|
@ -855,6 +1093,75 @@ namespace MWGui
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SelectSkillDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mControllerFocus < mSkillButtons.size())
|
||||
onSkillClicked(mSkillButtons[mControllerFocus]);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onCancelClicked(nullptr);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
mSkillButtons[mControllerFocus]->setStateSelected(false);
|
||||
mControllerFocus = wrap(mControllerFocus - 1, mSkillButtons.size());
|
||||
mSkillButtons[mControllerFocus]->setStateSelected(true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
mSkillButtons[mControllerFocus]->setStateSelected(false);
|
||||
mControllerFocus = wrap(mControllerFocus + 1, mSkillButtons.size());
|
||||
mSkillButtons[mControllerFocus]->setStateSelected(true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT || arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
|
||||
{
|
||||
mSkillButtons[mControllerFocus]->setStateSelected(false);
|
||||
selectNextColumn(arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT ? -1 : 1);
|
||||
mSkillButtons[mControllerFocus]->setStateSelected(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SelectSkillDialog::selectNextColumn(int direction)
|
||||
{
|
||||
// Find which column (specialization) the current index is in.
|
||||
size_t specialization = 0;
|
||||
size_t nextSpecializationIndex = 0;
|
||||
for (; specialization < mNumSkillsPerSpecialization.size(); ++specialization)
|
||||
{
|
||||
nextSpecializationIndex += mNumSkillsPerSpecialization[specialization];
|
||||
if (mControllerFocus < nextSpecializationIndex)
|
||||
break;
|
||||
}
|
||||
|
||||
if (direction < 0)
|
||||
{
|
||||
if (mControllerFocus < mNumSkillsPerSpecialization[0])
|
||||
{
|
||||
// Wrap around to the right column
|
||||
for (size_t i = 0; i < mNumSkillsPerSpecialization.size() - 1; ++i)
|
||||
mControllerFocus += mNumSkillsPerSpecialization[i];
|
||||
}
|
||||
else
|
||||
mControllerFocus -= mNumSkillsPerSpecialization[specialization];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mControllerFocus + mNumSkillsPerSpecialization.back() >= mSkillButtons.size())
|
||||
{
|
||||
// Wrap around to the left column
|
||||
for (size_t i = 0; i < mNumSkillsPerSpecialization.size() - 1; ++i)
|
||||
mControllerFocus -= mNumSkillsPerSpecialization[i];
|
||||
}
|
||||
else
|
||||
mControllerFocus += mNumSkillsPerSpecialization[specialization];
|
||||
}
|
||||
}
|
||||
|
||||
/* DescriptionDialog */
|
||||
|
||||
DescriptionDialog::DescriptionDialog()
|
||||
|
|
@ -873,6 +1180,8 @@ namespace MWGui
|
|||
|
||||
// Make sure the edit box has focus
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit);
|
||||
|
||||
mControllerButtons.mA = "#{Interface:OK}";
|
||||
}
|
||||
|
||||
DescriptionDialog::~DescriptionDialog() {}
|
||||
|
|
@ -904,4 +1213,13 @@ namespace MWGui
|
|||
imageBox->setImageTexture(classImage);
|
||||
}
|
||||
|
||||
bool DescriptionDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A || arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onOkClicked(nullptr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ namespace MWGui
|
|||
|
||||
protected:
|
||||
void onButtonClicked(MyGUI::Widget* _sender);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
|
||||
private:
|
||||
void fitToText(MyGUI::TextBox* widget);
|
||||
|
|
@ -50,6 +51,7 @@ namespace MWGui
|
|||
MyGUI::TextBox* mText;
|
||||
MyGUI::Widget* mButtonBar;
|
||||
std::vector<MyGUI::Button*> mButtons;
|
||||
size_t mControllerFocus;
|
||||
};
|
||||
|
||||
// Lets the player choose between 3 ways of creating a class
|
||||
|
|
@ -92,10 +94,14 @@ namespace MWGui
|
|||
protected:
|
||||
void onOkClicked(MyGUI::Widget* _sender);
|
||||
void onBackClicked(MyGUI::Widget* _sender);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
bool mOkButtonFocus = true;
|
||||
|
||||
private:
|
||||
MyGUI::ImageBox* mClassImage;
|
||||
MyGUI::TextBox* mClassName;
|
||||
MyGUI::Button* mBackButton;
|
||||
MyGUI::Button* mOkButton;
|
||||
|
||||
ESM::RefId mCurrentClassId;
|
||||
};
|
||||
|
|
@ -140,11 +146,15 @@ namespace MWGui
|
|||
MyGUI::ImageBox* mClassImage;
|
||||
MyGUI::ListBox* mClassList;
|
||||
MyGUI::TextBox* mSpecializationName;
|
||||
MyGUI::Button* mBackButton;
|
||||
MyGUI::Button* mOkButton;
|
||||
Widgets::MWAttributePtr mFavoriteAttribute[2];
|
||||
Widgets::MWSkillPtr mMajorSkill[5];
|
||||
Widgets::MWSkillPtr mMinorSkill[5];
|
||||
|
||||
ESM::RefId mCurrentClassId;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
};
|
||||
|
||||
class SelectSpecializationDialog : public WindowModal
|
||||
|
|
@ -173,6 +183,7 @@ namespace MWGui
|
|||
protected:
|
||||
void onSpecializationClicked(MyGUI::Widget* _sender);
|
||||
void onCancelClicked(MyGUI::Widget* _sender);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
|
||||
private:
|
||||
MyGUI::TextBox *mSpecialization0, *mSpecialization1, *mSpecialization2;
|
||||
|
|
@ -206,6 +217,9 @@ namespace MWGui
|
|||
protected:
|
||||
void onAttributeClicked(Widgets::MWAttributePtr _sender);
|
||||
void onCancelClicked(MyGUI::Widget* _sender);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
size_t mControllerFocus;
|
||||
std::vector<Widgets::MWAttribute*> mAttributeButtons;
|
||||
|
||||
private:
|
||||
ESM::RefId mAttributeId;
|
||||
|
|
@ -237,9 +251,15 @@ namespace MWGui
|
|||
protected:
|
||||
void onSkillClicked(Widgets::MWSkillPtr _sender);
|
||||
void onCancelClicked(MyGUI::Widget* _sender);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
size_t mControllerFocus;
|
||||
std::vector<Widgets::MWSkill*> mSkillButtons;
|
||||
|
||||
private:
|
||||
ESM::RefId mSkillId;
|
||||
std::array<size_t, 3> mNumSkillsPerSpecialization;
|
||||
|
||||
void selectNextColumn(int direction);
|
||||
};
|
||||
|
||||
class DescriptionDialog : public WindowModal
|
||||
|
|
@ -258,6 +278,7 @@ namespace MWGui
|
|||
|
||||
protected:
|
||||
void onOkClicked(MyGUI::Widget* _sender);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
|
||||
private:
|
||||
MyGUI::EditBox* mTextEdit;
|
||||
|
|
@ -314,6 +335,7 @@ namespace MWGui
|
|||
private:
|
||||
MyGUI::EditBox* mEditName;
|
||||
MyGUI::TextBox* mSpecializationName;
|
||||
std::vector<MyGUI::Button*> mButtons;
|
||||
Widgets::MWAttributePtr mFavoriteAttribute0, mFavoriteAttribute1;
|
||||
std::array<Widgets::MWSkillPtr, 5> mMajorSkill;
|
||||
std::array<Widgets::MWSkillPtr, 5> mMinorSkill;
|
||||
|
|
@ -329,6 +351,9 @@ namespace MWGui
|
|||
|
||||
Widgets::MWAttributePtr mAffectedAttribute;
|
||||
Widgets::MWSkillPtr mAffectedSkill;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
size_t mControllerFocus;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#include <MyGUI_EditBox.h>
|
||||
#include <MyGUI_InputManager.h>
|
||||
|
||||
#include <components/settings/values.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
|
|
@ -61,6 +63,11 @@ namespace MWGui
|
|||
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CompanionWindow::onCloseButtonClicked);
|
||||
|
||||
setCoord(200, 0, 600, 300);
|
||||
|
||||
mControllerButtons.mA = "#{sTake}";
|
||||
mControllerButtons.mB = "#{Interface:Close}";
|
||||
mControllerButtons.mR3 = "#{sInfo}";
|
||||
mControllerButtons.mL2 = "#{sInventory}";
|
||||
}
|
||||
|
||||
void CompanionWindow::onItemSelected(int index)
|
||||
|
|
@ -96,13 +103,12 @@ namespace MWGui
|
|||
name += MWGui::ToolTips::getSoulString(object.getCellRef());
|
||||
dialog->openCountDialog(name, "#{sTake}", count);
|
||||
dialog->eventOkClicked.clear();
|
||||
|
||||
if (MyGUI::InputManager::getInstance().isAltPressed())
|
||||
if (Settings::gui().mControllerMenus || MyGUI::InputManager::getInstance().isAltPressed())
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &CompanionWindow::transferItem);
|
||||
else
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &CompanionWindow::dragItem);
|
||||
}
|
||||
else if (MyGUI::InputManager::getInstance().isAltPressed())
|
||||
else if (Settings::gui().mControllerMenus || MyGUI::InputManager::getInstance().isAltPressed())
|
||||
transferItem(nullptr, count);
|
||||
else
|
||||
dragItem(nullptr, count);
|
||||
|
|
@ -243,4 +249,32 @@ namespace MWGui
|
|||
{
|
||||
mItemTransfer->removeTarget(*mItemView);
|
||||
}
|
||||
|
||||
bool CompanionWindow::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)
|
||||
{
|
||||
onCloseButtonClicked(mCloseButton);
|
||||
}
|
||||
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->onControllerButton(arg.button);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CompanionWindow::setActiveControllerWindow(bool active)
|
||||
{
|
||||
mItemView->setActiveControllerWindow(active);
|
||||
WindowBase::setActiveControllerWindow(active);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,12 @@ namespace MWGui
|
|||
|
||||
std::string_view getWindowIdForLua() const override { return "Companion"; }
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
void setActiveControllerWindow(bool active) override;
|
||||
|
||||
MWGui::ItemView* getItemView() { return mItemView; }
|
||||
CompanionItemModel* getModel() { return mModel; }
|
||||
|
||||
private:
|
||||
ItemView* mItemView;
|
||||
SortFilterItemModel* mSortModel;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include <MyGUI_Button.h>
|
||||
#include <MyGUI_EditBox.h>
|
||||
|
||||
#include <components/settings/values.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
|
|
@ -17,6 +19,13 @@ namespace MWGui
|
|||
|
||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ConfirmationDialog::onCancelButtonClicked);
|
||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ConfirmationDialog::onOkButtonClicked);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mDisableGamepadCursor = true;
|
||||
mControllerButtons.mA = "#{Interface:OK}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
}
|
||||
}
|
||||
|
||||
void ConfirmationDialog::askForConfirmation(const std::string& message)
|
||||
|
|
@ -35,6 +44,13 @@ namespace MWGui
|
|||
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mOkButton);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mOkButtonFocus = true;
|
||||
mOkButton->setStateSelected(true);
|
||||
mCancelButton->setStateSelected(false);
|
||||
}
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
|
|
@ -56,4 +72,28 @@ namespace MWGui
|
|||
|
||||
eventOkClicked();
|
||||
}
|
||||
|
||||
bool ConfirmationDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mOkButtonFocus)
|
||||
onOkButtonClicked(mOkButton);
|
||||
else
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
}
|
||||
else if ((arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT && !mOkButtonFocus)
|
||||
|| (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT && mOkButtonFocus))
|
||||
{
|
||||
mOkButtonFocus = !mOkButtonFocus;
|
||||
mOkButton->setStateSelected(mOkButtonFocus);
|
||||
mCancelButton->setStateSelected(!mOkButtonFocus);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ namespace MWGui
|
|||
|
||||
void onCancelButtonClicked(MyGUI::Widget* _sender);
|
||||
void onOkButtonClicked(MyGUI::Widget* _sender);
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
bool mOkButtonFocus = true;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include <MyGUI_Button.h>
|
||||
#include <MyGUI_InputManager.h>
|
||||
|
||||
#include <components/settings/values.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/scriptmanager.hpp"
|
||||
|
|
@ -56,6 +58,12 @@ namespace MWGui
|
|||
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked);
|
||||
|
||||
setCoord(200, 0, 600, 300);
|
||||
|
||||
mControllerButtons.mA = "#{sTake}";
|
||||
mControllerButtons.mB = "#{Interface:Close}";
|
||||
mControllerButtons.mX = "#{sTakeAll}";
|
||||
mControllerButtons.mR3 = "#{sInfo}";
|
||||
mControllerButtons.mL2 = "#{sInventory}";
|
||||
}
|
||||
|
||||
void ContainerWindow::onItemSelected(int index)
|
||||
|
|
@ -90,13 +98,12 @@ namespace MWGui
|
|||
name += MWGui::ToolTips::getSoulString(object.getCellRef());
|
||||
dialog->openCountDialog(name, "#{sTake}", count);
|
||||
dialog->eventOkClicked.clear();
|
||||
|
||||
if (MyGUI::InputManager::getInstance().isAltPressed())
|
||||
if (Settings::gui().mControllerMenus || MyGUI::InputManager::getInstance().isAltPressed())
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::transferItem);
|
||||
else
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::dragItem);
|
||||
}
|
||||
else if (MyGUI::InputManager::getInstance().isAltPressed())
|
||||
else if (Settings::gui().mControllerMenus || MyGUI::InputManager::getInstance().isAltPressed())
|
||||
transferItem(nullptr, count);
|
||||
else
|
||||
dragItem(nullptr, count);
|
||||
|
|
@ -346,6 +353,49 @@ namespace MWGui
|
|||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
||||
}
|
||||
|
||||
ControllerButtons* ContainerWindow::getControllerButtons()
|
||||
{
|
||||
mControllerButtons.mR1 = mDisposeCorpseButton->getVisible() ? "#{sDisposeofCorpse}" : "";
|
||||
return &mControllerButtons;
|
||||
}
|
||||
|
||||
bool ContainerWindow::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)
|
||||
{
|
||||
onCloseButtonClicked(mCloseButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
{
|
||||
onTakeAllButtonClicked(mTakeButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
|
||||
{
|
||||
if (mDisposeCorpseButton->getVisible())
|
||||
onDisposeCorpseButtonClicked(mDisposeCorpseButton);
|
||||
}
|
||||
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->onControllerButton(arg.button);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ContainerWindow::setActiveControllerWindow(bool active)
|
||||
{
|
||||
mItemView->setActiveControllerWindow(active);
|
||||
WindowBase::setActiveControllerWindow(active);
|
||||
}
|
||||
|
||||
void ContainerWindow::onFrame(float dt)
|
||||
{
|
||||
checkReferenceAvailable();
|
||||
|
|
|
|||
|
|
@ -48,6 +48,13 @@ namespace MWGui
|
|||
|
||||
std::string_view getWindowIdForLua() const override { return "Container"; }
|
||||
|
||||
ControllerButtons* getControllerButtons() override;
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
void setActiveControllerWindow(bool active) override;
|
||||
|
||||
MWGui::ItemView* getItemView() { return mItemView; }
|
||||
ItemModel* getModel() { return mModel; }
|
||||
|
||||
private:
|
||||
Misc::NotNullPtr<DragAndDrop> mDragAndDrop;
|
||||
Misc::NotNullPtr<ItemTransfer> mItemTransfer;
|
||||
|
|
|
|||
106
apps/openmw/mwgui/controllerbuttonsoverlay.cpp
Normal file
106
apps/openmw/mwgui/controllerbuttonsoverlay.cpp
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#include "controllerbuttonsoverlay.hpp"
|
||||
|
||||
#include <MyGUI_Window.h>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
static constexpr ControllerButtonsOverlay::ButtonDefinition sButtonDefs[] = {
|
||||
{ ControllerButtonsOverlay::Button::Button_A, "A", ControllerButtonsOverlay::InputType_Button,
|
||||
{ .mButton = SDL_CONTROLLER_BUTTON_A }, &ControllerButtons::mA },
|
||||
{ ControllerButtonsOverlay::Button::Button_B, "B", ControllerButtonsOverlay::InputType_Button,
|
||||
{ .mButton = SDL_CONTROLLER_BUTTON_B }, &ControllerButtons::mB },
|
||||
{ ControllerButtonsOverlay::Button::Button_Dpad, "Dpad", ControllerButtonsOverlay::InputType_Button,
|
||||
{ .mButton = SDL_CONTROLLER_BUTTON_DPAD_UP }, &ControllerButtons::mDpad },
|
||||
{ ControllerButtonsOverlay::Button::Button_L1, "L1", ControllerButtonsOverlay::InputType_Button,
|
||||
{ .mButton = SDL_CONTROLLER_BUTTON_LEFTSHOULDER }, &ControllerButtons::mL1 },
|
||||
{ ControllerButtonsOverlay::Button::Button_L2, "L2", ControllerButtonsOverlay::InputType_Axis,
|
||||
{ .mAxis = SDL_CONTROLLER_AXIS_TRIGGERLEFT }, &ControllerButtons::mL2 },
|
||||
{ ControllerButtonsOverlay::Button::Button_L3, "L3", ControllerButtonsOverlay::InputType_Button,
|
||||
{ .mButton = SDL_CONTROLLER_BUTTON_LEFTSTICK }, &ControllerButtons::mL3 },
|
||||
{ ControllerButtonsOverlay::Button::Button_LStick, "LStick", ControllerButtonsOverlay::InputType_Axis,
|
||||
{ .mAxis = SDL_CONTROLLER_AXIS_LEFTY }, &ControllerButtons::mLStick },
|
||||
{ ControllerButtonsOverlay::Button::Button_Menu, "Menu", ControllerButtonsOverlay::InputType_Button,
|
||||
{ .mButton = SDL_CONTROLLER_BUTTON_BACK }, &ControllerButtons::mMenu },
|
||||
{ ControllerButtonsOverlay::Button::Button_R1, "R1", ControllerButtonsOverlay::InputType_Button,
|
||||
{ .mButton = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER }, &ControllerButtons::mR1 },
|
||||
{ ControllerButtonsOverlay::Button::Button_R2, "R2", ControllerButtonsOverlay::InputType_Axis,
|
||||
{ .mAxis = SDL_CONTROLLER_AXIS_TRIGGERRIGHT }, &ControllerButtons::mR2 },
|
||||
{ ControllerButtonsOverlay::Button::Button_R3, "R3", ControllerButtonsOverlay::InputType_Button,
|
||||
{ .mButton = SDL_CONTROLLER_BUTTON_RIGHTSTICK }, &ControllerButtons::mR3 },
|
||||
{ ControllerButtonsOverlay::Button::Button_RStick, "RStick", ControllerButtonsOverlay::InputType_Axis,
|
||||
{ .mAxis = SDL_CONTROLLER_AXIS_RIGHTY }, &ControllerButtons::mRStick },
|
||||
{ ControllerButtonsOverlay::Button::Button_View, "View", ControllerButtonsOverlay::InputType_Button,
|
||||
{ .mButton = SDL_CONTROLLER_BUTTON_START }, &ControllerButtons::mView },
|
||||
{ ControllerButtonsOverlay::Button::Button_X, "X", ControllerButtonsOverlay::InputType_Button,
|
||||
{ .mButton = SDL_CONTROLLER_BUTTON_X }, &ControllerButtons::mX },
|
||||
{ ControllerButtonsOverlay::Button::Button_Y, "Y", ControllerButtonsOverlay::InputType_Button,
|
||||
{ .mButton = SDL_CONTROLLER_BUTTON_Y }, &ControllerButtons::mY },
|
||||
};
|
||||
|
||||
ControllerButtonsOverlay::ControllerButtonsOverlay()
|
||||
: WindowBase("openmw_controllerbuttons.layout")
|
||||
{
|
||||
MWBase::InputManager* inputMgr = MWBase::Environment::get().getInputManager();
|
||||
|
||||
for (size_t i = 0; i < mButtons.size(); i++)
|
||||
{
|
||||
getWidget(mButtons[i].mImage, "Btn" + sButtonDefs[i].mName + "Image");
|
||||
getWidget(mButtons[i].mText, "Btn" + sButtonDefs[i].mName + "Text");
|
||||
getWidget(mButtons[i].mHBox, "Btn" + sButtonDefs[i].mName);
|
||||
|
||||
if (sButtonDefs[i].mInputType == InputType_Axis)
|
||||
setIcon(mButtons[i].mImage, inputMgr->getControllerAxisIcon(sButtonDefs[i].mId.mAxis));
|
||||
else
|
||||
setIcon(mButtons[i].mImage, inputMgr->getControllerButtonIcon(sButtonDefs[i].mId.mButton));
|
||||
}
|
||||
|
||||
getWidget(mHBox, "ButtonBox");
|
||||
}
|
||||
|
||||
int ControllerButtonsOverlay::getHeight()
|
||||
{
|
||||
MyGUI::Window* window = mMainWidget->castType<MyGUI::Window>();
|
||||
return window->getHeight();
|
||||
}
|
||||
|
||||
void ControllerButtonsOverlay::setButtons(ControllerButtons* buttons)
|
||||
{
|
||||
int buttonCount = 0;
|
||||
if (buttons != nullptr)
|
||||
{
|
||||
for (const auto& row : sButtonDefs)
|
||||
buttonCount += updateButton(row.mButton, buttons->*(row.mField));
|
||||
|
||||
mHBox->notifyChildrenSizeChanged();
|
||||
}
|
||||
|
||||
setVisible(buttonCount > 0);
|
||||
}
|
||||
|
||||
void ControllerButtonsOverlay::setIcon(MyGUI::ImageBox* image, const std::string& imagePath)
|
||||
{
|
||||
if (!imagePath.empty())
|
||||
image->setImageTexture(imagePath);
|
||||
}
|
||||
|
||||
int ControllerButtonsOverlay::updateButton(ControllerButtonsOverlay::Button button, const std::string& buttonStr)
|
||||
{
|
||||
if (buttonStr.empty())
|
||||
{
|
||||
mButtons[button].mHBox->setVisible(false);
|
||||
mButtons[button].mHBox->setUserString("Hidden", "true");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mButtons[button].mHBox->setVisible(true);
|
||||
mButtons[button].mHBox->setUserString("Hidden", "false");
|
||||
mButtons[button].mText->setCaptionWithReplacing(buttonStr);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
83
apps/openmw/mwgui/controllerbuttonsoverlay.hpp
Normal file
83
apps/openmw/mwgui/controllerbuttonsoverlay.hpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#ifndef MWGUI_CONTROLLERBUTTONSOVERLAY_H
|
||||
#define MWGUI_CONTROLLERBUTTONSOVERLAY_H
|
||||
|
||||
#include <MyGUI_ImageBox.h>
|
||||
#include <MyGUI_TextBox.h>
|
||||
|
||||
#include <components/widgets/box.hpp>
|
||||
|
||||
#include "windowbase.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class ControllerButtonsOverlay : public WindowBase
|
||||
{
|
||||
public:
|
||||
ControllerButtonsOverlay();
|
||||
|
||||
int getHeight();
|
||||
void setButtons(ControllerButtons* buttons);
|
||||
|
||||
enum Button
|
||||
{
|
||||
Button_A = 0,
|
||||
Button_B,
|
||||
Button_Dpad,
|
||||
Button_L1,
|
||||
Button_L2,
|
||||
Button_L3,
|
||||
Button_LStick,
|
||||
Button_Menu,
|
||||
Button_R1,
|
||||
Button_R2,
|
||||
Button_R3,
|
||||
Button_RStick,
|
||||
Button_View,
|
||||
Button_X,
|
||||
Button_Y,
|
||||
Button_Max,
|
||||
};
|
||||
|
||||
enum InputType
|
||||
{
|
||||
InputType_Button,
|
||||
InputType_Axis
|
||||
};
|
||||
|
||||
struct ButtonDefinition
|
||||
{
|
||||
Button mButton;
|
||||
std::string mName;
|
||||
InputType mInputType;
|
||||
union
|
||||
{
|
||||
SDL_GameControllerButton mButton;
|
||||
SDL_GameControllerAxis mAxis;
|
||||
} mId;
|
||||
std::string MWGui::ControllerButtons::*mField;
|
||||
};
|
||||
|
||||
private:
|
||||
struct ButtonWidgets
|
||||
{
|
||||
MyGUI::ImageBox* mImage;
|
||||
MyGUI::TextBox* mText;
|
||||
Gui::HBox* mHBox;
|
||||
|
||||
ButtonWidgets()
|
||||
: mImage(nullptr)
|
||||
, mText(nullptr)
|
||||
, mHBox(nullptr)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
std::array<ButtonWidgets, Button::Button_Max> mButtons;
|
||||
Gui::HBox* mHBox;
|
||||
|
||||
void setIcon(MyGUI::ImageBox* image, const std::string& imagePath);
|
||||
int updateButton(Button button, const std::string& buttonStr);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -27,6 +27,9 @@ namespace MWGui
|
|||
mSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &CountDialog::onSliderMoved);
|
||||
// make sure we read the enter key being pressed to accept multiple items
|
||||
mItemEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &CountDialog::onEnterKeyPressed);
|
||||
|
||||
mControllerButtons.mA = "#{Interface:OK}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
}
|
||||
|
||||
void CountDialog::openCountDialog(const std::string& item, const std::string& message, const int maxCount)
|
||||
|
|
@ -38,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,
|
||||
|
|
@ -54,6 +57,13 @@ namespace MWGui
|
|||
mItemEdit->setValue(maxCount);
|
||||
}
|
||||
|
||||
void CountDialog::setCount(int count)
|
||||
{
|
||||
count = std::clamp(count, 1, static_cast<int>(mSlider->getScrollRange()));
|
||||
mSlider->setScrollPosition(count - 1);
|
||||
mItemEdit->setValue(count);
|
||||
}
|
||||
|
||||
void CountDialog::onCancelButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
setVisible(false);
|
||||
|
|
@ -61,17 +71,16 @@ namespace MWGui
|
|||
|
||||
void CountDialog::onOkButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
eventOkClicked(nullptr, mSlider->getScrollPosition() + 1);
|
||||
|
||||
// The order here matters. Hide the dialog first so the OK event tooltips reappear.
|
||||
setVisible(false);
|
||||
eventOkClicked(nullptr, mSlider->getScrollPosition() + 1);
|
||||
}
|
||||
|
||||
// essentially duplicating what the OK button does if user presses
|
||||
// Enter key
|
||||
void CountDialog::onEnterKeyPressed(MyGUI::EditBox* _sender)
|
||||
{
|
||||
eventOkClicked(nullptr, mSlider->getScrollPosition() + 1);
|
||||
setVisible(false);
|
||||
onOkButtonClicked(_sender);
|
||||
|
||||
// To do not spam onEnterKeyPressed() again and again
|
||||
MWBase::Environment::get().getWindowManager()->injectKeyRelease(MyGUI::KeyCode::None);
|
||||
|
|
@ -86,4 +95,22 @@ namespace MWGui
|
|||
{
|
||||
mItemEdit->setValue(_position + 1);
|
||||
}
|
||||
|
||||
bool CountDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
onOkButtonClicked(mOkButton);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
|
||||
setCount(1);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
|
||||
setCount(static_cast<int>(mSlider->getScrollRange()));
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
|
||||
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::ArrowDown, 0, false);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
|
||||
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::ArrowUp, 0, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ namespace MWGui
|
|||
public:
|
||||
CountDialog();
|
||||
void openCountDialog(const std::string& item, const std::string& message, const int maxCount);
|
||||
void setCount(int count);
|
||||
|
||||
/** Event : Ok button was clicked.\n
|
||||
signature : void method(MyGUI::Widget* sender, std::size_t count)\n
|
||||
|
|
@ -34,6 +35,7 @@ namespace MWGui
|
|||
void onEditValueChanged(int value);
|
||||
void onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position);
|
||||
void onEnterKeyPressed(MyGUI::EditBox* _sender);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,10 @@ namespace MWGui
|
|||
mBribe10Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade);
|
||||
mBribe100Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade);
|
||||
mBribe1000Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade);
|
||||
|
||||
mDisableGamepadCursor = Settings::gui().mControllerMenus;
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
}
|
||||
|
||||
void PersuasionDialog::adjustAction(MyGUI::Widget* action, int& totalHeight)
|
||||
|
|
@ -144,6 +148,24 @@ namespace MWGui
|
|||
else
|
||||
mMainWidget->setSize(mInitialMainWidgetWidth, mMainWidget->getSize().height);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerFocus = 0;
|
||||
mButtons.clear();
|
||||
mButtons.push_back(mAdmireButton);
|
||||
mButtons.push_back(mIntimidateButton);
|
||||
mButtons.push_back(mTauntButton);
|
||||
if (mBribe10Button->getEnabled())
|
||||
mButtons.push_back(mBribe10Button);
|
||||
if (mBribe100Button->getEnabled())
|
||||
mButtons.push_back(mBribe100Button);
|
||||
if (mBribe1000Button->getEnabled())
|
||||
mButtons.push_back(mBribe1000Button);
|
||||
|
||||
for (size_t i = 0; i < mButtons.size(); i++)
|
||||
mButtons[i]->setStateSelected(i == 0);
|
||||
}
|
||||
|
||||
WindowModal::onOpen();
|
||||
}
|
||||
|
||||
|
|
@ -152,6 +174,31 @@ namespace MWGui
|
|||
return mAdmireButton;
|
||||
}
|
||||
|
||||
bool PersuasionDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
onPersuade(mButtons[mControllerFocus]);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
onCancel(mCancelButton);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
setControllerFocus(mButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus - 1, mButtons.size());
|
||||
setControllerFocus(mButtons, mControllerFocus, true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
setControllerFocus(mButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus + 1, mButtons.size());
|
||||
setControllerFocus(mButtons, mControllerFocus, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
|
||||
Response::Response(std::string_view text, std::string_view title, bool needMargin)
|
||||
|
|
@ -300,6 +347,9 @@ namespace MWGui
|
|||
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
|
||||
// Morrowind uses 3 px invisible borders for padding topics
|
||||
static constexpr int sVerticalPadding = 3;
|
||||
|
||||
DialogueWindow::DialogueWindow()
|
||||
: WindowBase("openmw_dialogue_window.layout")
|
||||
, mIsCompanion(false)
|
||||
|
|
@ -335,6 +385,11 @@ namespace MWGui
|
|||
|
||||
mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord
|
||||
+= MyGUI::newDelegate(this, &DialogueWindow::onWindowResize);
|
||||
|
||||
mControllerScrollWidget = mHistory->getParent();
|
||||
mControllerButtons.mA = "#{sAsk}";
|
||||
mControllerButtons.mB = "#{sGoodbye}";
|
||||
mControllerButtons.mRStick = "#{sScrollup}";
|
||||
}
|
||||
|
||||
void DialogueWindow::onTradeComplete()
|
||||
|
|
@ -488,6 +543,14 @@ namespace MWGui
|
|||
updateTopics();
|
||||
updateTopicsPane(); // force update for new services
|
||||
|
||||
if (Settings::gui().mControllerMenus && !sameActor)
|
||||
{
|
||||
setControllerFocus(mControllerFocus, false);
|
||||
// Reset focus to very top. Maybe change this to mTopicsList->getItemCount() - mKeywords.size()?
|
||||
mControllerFocus = 0;
|
||||
setControllerFocus(mControllerFocus, true);
|
||||
}
|
||||
|
||||
updateDisposition();
|
||||
restock();
|
||||
}
|
||||
|
|
@ -543,6 +606,10 @@ namespace MWGui
|
|||
|
||||
void DialogueWindow::updateTopicsPane()
|
||||
{
|
||||
std::string focusedTopic;
|
||||
if (Settings::gui().mControllerMenus && mControllerFocus < static_cast<int>(mTopicsList->getItemCount()))
|
||||
focusedTopic = mTopicsList->getItemNameAt(mControllerFocus);
|
||||
|
||||
mTopicsList->clear();
|
||||
for (auto& linkPair : mTopicLinks)
|
||||
mDeleteLater.push_back(std::move(linkPair.second));
|
||||
|
|
@ -588,22 +655,25 @@ namespace MWGui
|
|||
if (mTopicsList->getItemCount() > 0)
|
||||
mTopicsList->addSeparator();
|
||||
|
||||
// Morrowind uses 3 px invisible borders for padding topics
|
||||
constexpr int verticalPadding = 3;
|
||||
|
||||
for (const auto& keyword : mKeywords)
|
||||
{
|
||||
std::string topicId = Misc::StringUtils::lowerCase(keyword);
|
||||
mTopicsList->addItem(keyword, verticalPadding);
|
||||
mTopicsList->addItem(keyword, sVerticalPadding);
|
||||
|
||||
auto t = std::make_unique<Topic>(keyword);
|
||||
mKeywordSearch.seed(topicId, intptr_t(t.get()));
|
||||
t->eventTopicActivated += MyGUI::newDelegate(this, &DialogueWindow::onTopicActivated);
|
||||
mTopicLinks[topicId] = std::move(t);
|
||||
|
||||
if (keyword == focusedTopic)
|
||||
mControllerFocus = mTopicsList->getItemCount() - 1;
|
||||
}
|
||||
|
||||
redrawTopicsList();
|
||||
updateHistory();
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
setControllerFocus(mControllerFocus, true);
|
||||
}
|
||||
|
||||
void DialogueWindow::updateHistory(bool scrollbar)
|
||||
|
|
@ -630,6 +700,8 @@ namespace MWGui
|
|||
// choices
|
||||
const TextColours& textColours = MWBase::Environment::get().getWindowManager()->getTextColours();
|
||||
mChoices = MWBase::Environment::get().getDialogueManager()->getChoices();
|
||||
mChoiceStyles.clear();
|
||||
mControllerChoice = -1; // -1 so you must make a choice (and can't accidentally pick the first answer)
|
||||
for (std::pair<std::string, int>& choice : mChoices)
|
||||
{
|
||||
auto link = std::make_unique<Choice>(choice.second);
|
||||
|
|
@ -641,6 +713,7 @@ namespace MWGui
|
|||
BookTypesetter::Style* questionStyle = typesetter->createHotStyle(
|
||||
body, textColours.answer, textColours.answerOver, textColours.answerPressed, interactiveId);
|
||||
typesetter->write(questionStyle, to_utf8_span(choice.first));
|
||||
mChoiceStyles.push_back(questionStyle);
|
||||
}
|
||||
|
||||
mGoodbye = MWBase::Environment::get().getDialogueManager()->isGoodbye();
|
||||
|
|
@ -850,4 +923,120 @@ namespace MWGui
|
|||
&& actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion");
|
||||
}
|
||||
|
||||
void DialogueWindow::setControllerFocus(size_t index, bool focused)
|
||||
{
|
||||
// List is mTopicsList + "Goodbye" button below the list.
|
||||
if (index > mTopicsList->getItemCount())
|
||||
return;
|
||||
|
||||
if (index == mTopicsList->getItemCount())
|
||||
{
|
||||
mGoodbyeButton->setStateSelected(focused);
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string& keyword = mTopicsList->getItemNameAt(mControllerFocus);
|
||||
if (keyword.empty())
|
||||
return;
|
||||
|
||||
MyGUI::Button* button = mTopicsList->getItemWidget(keyword);
|
||||
button->setStateSelected(focused);
|
||||
}
|
||||
|
||||
if (focused)
|
||||
{
|
||||
// Scroll the side bar to keep the active item in view
|
||||
int offset = 0;
|
||||
for (int i = 6; i < static_cast<int>(index); i++)
|
||||
{
|
||||
const std::string& keyword = mTopicsList->getItemNameAt(i);
|
||||
if (keyword.empty())
|
||||
offset += 18 + sVerticalPadding * 2;
|
||||
else
|
||||
offset += mTopicsList->getItemWidget(keyword)->getHeight() + sVerticalPadding * 2;
|
||||
}
|
||||
mTopicsList->setViewOffset(-offset);
|
||||
}
|
||||
}
|
||||
|
||||
bool DialogueWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mChoices.size() > 0)
|
||||
{
|
||||
if (mChoices.size() == 1)
|
||||
onChoiceActivated(mChoices[0].second);
|
||||
else if (mControllerChoice >= 0 && mControllerChoice < static_cast<int>(mChoices.size()))
|
||||
onChoiceActivated(mChoices[mControllerChoice].second);
|
||||
}
|
||||
else if (mControllerFocus == static_cast<int>(mTopicsList->getItemCount()))
|
||||
onGoodbyeActivated();
|
||||
else
|
||||
onSelectListItem(mTopicsList->getItemNameAt(mControllerFocus), mControllerFocus);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B && mChoices.empty())
|
||||
{
|
||||
onGoodbyeActivated();
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
if (mChoices.size() > 0)
|
||||
{
|
||||
// In-dialogue choice (red text)
|
||||
mControllerChoice = std::clamp(mControllerChoice - 1, 0, static_cast<int>(mChoices.size()) - 1);
|
||||
mHistory->setFocusItem(mChoiceStyles.at(mControllerChoice));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Number of items is mTopicsList.length+1 because of "Goodbye" button.
|
||||
setControllerFocus(mControllerFocus, false);
|
||||
if (mControllerFocus <= 0)
|
||||
mControllerFocus = mTopicsList->getItemCount(); // "Goodbye" button
|
||||
else if (mTopicsList->getItemNameAt(mControllerFocus - 1).empty())
|
||||
mControllerFocus -= 2; // Skip separator
|
||||
else
|
||||
mControllerFocus--;
|
||||
setControllerFocus(mControllerFocus, true);
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
if (mChoices.size() > 0)
|
||||
{
|
||||
// In-dialogue choice (red text)
|
||||
mControllerChoice = std::clamp(mControllerChoice + 1, 0, static_cast<int>(mChoices.size()) - 1);
|
||||
mHistory->setFocusItem(mChoiceStyles.at(mControllerChoice));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Number of items is mTopicsList.length+1 because of "Goodbye" button.
|
||||
setControllerFocus(mControllerFocus, false);
|
||||
if (mControllerFocus >= static_cast<int>(mTopicsList->getItemCount()))
|
||||
mControllerFocus = 0;
|
||||
else if (mControllerFocus == static_cast<int>(mTopicsList->getItemCount()) - 1)
|
||||
mControllerFocus = mTopicsList->getItemCount(); // "Goodbye" button
|
||||
else if (mTopicsList->getItemNameAt(mControllerFocus + 1).empty())
|
||||
mControllerFocus += 2; // Skip separator
|
||||
else
|
||||
mControllerFocus++;
|
||||
setControllerFocus(mControllerFocus, true);
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER && mChoices.size() == 0)
|
||||
{
|
||||
setControllerFocus(mControllerFocus, false);
|
||||
mControllerFocus = std::max(mControllerFocus - 5, 0);
|
||||
setControllerFocus(mControllerFocus, true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER && mChoices.size() == 0)
|
||||
{
|
||||
setControllerFocus(mControllerFocus, false);
|
||||
mControllerFocus = std::min(mControllerFocus + 5, static_cast<int>(mTopicsList->getItemCount()));
|
||||
setControllerFocus(mControllerFocus, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ namespace MWGui
|
|||
|
||||
MyGUI::Widget* getDefaultKeyFocus() override;
|
||||
|
||||
protected:
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<ResponseCallback> mCallback;
|
||||
|
||||
|
|
@ -65,6 +68,9 @@ namespace MWGui
|
|||
MyGUI::Widget* mActionsBox;
|
||||
Gui::AutoSizedTextBox* mGoldLabel;
|
||||
|
||||
std::vector<MyGUI::Button*> mButtons;
|
||||
int mControllerFocus = 0;
|
||||
|
||||
void adjustAction(MyGUI::Widget* action, int& totalHeight);
|
||||
|
||||
void onCancel(MyGUI::Widget* sender);
|
||||
|
|
@ -186,6 +192,8 @@ namespace MWGui
|
|||
|
||||
void onReferenceUnavailable() override;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
|
||||
private:
|
||||
void updateDisposition();
|
||||
void restock();
|
||||
|
|
@ -197,6 +205,7 @@ namespace MWGui
|
|||
|
||||
std::vector<std::unique_ptr<DialogueText>> mHistoryContents;
|
||||
std::vector<std::pair<std::string, int>> mChoices;
|
||||
std::vector<BookTypesetter::Style*> mChoiceStyles;
|
||||
bool mGoodbye;
|
||||
|
||||
std::vector<std::unique_ptr<Link>> mLinks;
|
||||
|
|
@ -220,6 +229,10 @@ namespace MWGui
|
|||
std::unique_ptr<ResponseCallback> mCallback;
|
||||
std::unique_ptr<ResponseCallback> mGreetingCallback;
|
||||
|
||||
void setControllerFocus(size_t index, bool focused);
|
||||
int mControllerFocus = 0;
|
||||
int mControllerChoice = -1;
|
||||
|
||||
void updateTopicFormat();
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,12 @@ namespace MWGui
|
|||
mBuyButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onBuyButtonClicked);
|
||||
mTypeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onTypeButtonClicked);
|
||||
mName->eventEditSelectAccept += MyGUI::newDelegate(this, &EnchantingDialog::onAccept);
|
||||
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
mControllerButtons.mY = "#{OMWEngine:EnchantType}";
|
||||
mControllerButtons.mL1 = "#{sItem}";
|
||||
mControllerButtons.mR1 = "#{sSoulGem}";
|
||||
}
|
||||
|
||||
void EnchantingDialog::onOpen()
|
||||
|
|
@ -152,6 +158,7 @@ namespace MWGui
|
|||
mEnchanting.setSelfEnchanting(false);
|
||||
mEnchanting.setEnchanter(ptr);
|
||||
mBuyButton->setCaptionWithReplacing("#{sBuy}");
|
||||
mControllerButtons.mX = "#{sBuy}";
|
||||
mChanceLayout->setVisible(false);
|
||||
mPtr = ptr;
|
||||
setSoulGem(MWWorld::Ptr());
|
||||
|
|
@ -163,6 +170,7 @@ namespace MWGui
|
|||
mEnchanting.setSelfEnchanting(true);
|
||||
mEnchanting.setEnchanter(MWMechanics::getPlayer());
|
||||
mBuyButton->setCaptionWithReplacing("#{sCreate}");
|
||||
mControllerButtons.mX = "#{sCreate}";
|
||||
mChanceLayout->setVisible(Settings::game().mShowEnchantChance);
|
||||
mPtr = MWMechanics::getPlayer();
|
||||
setSoulGem(ptr);
|
||||
|
|
@ -382,4 +390,22 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool EnchantingDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
onBuyButtonClicked(mBuyButton);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_Y)
|
||||
onTypeButtonClicked(mTypeButton);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
|
||||
onSelectItem(mItemBox);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
|
||||
onSelectSoul(mSoulBox);
|
||||
else
|
||||
return EffectEditorBase::onControllerButtonEvent(arg);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ namespace MWGui
|
|||
|
||||
MWMechanics::Enchanting mEnchanting;
|
||||
ESM::EffectList mEffectList;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,6 +188,17 @@ namespace MWGui
|
|||
mDrowningBar->setVisible(visible);
|
||||
}
|
||||
|
||||
void HUD::dropDraggedItem(float mouseX, float mouseY)
|
||||
{
|
||||
if (!mDragAndDrop->mIsOnDragAndDrop)
|
||||
return;
|
||||
|
||||
MWBase::Environment::get().getWorld()->breakInvisibility(MWMechanics::getPlayer());
|
||||
|
||||
WorldItemModel drop(mouseX, mouseY);
|
||||
mDragAndDrop->drop(&drop, nullptr);
|
||||
}
|
||||
|
||||
void HUD::onWorldClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ namespace MWGui
|
|||
|
||||
void clear() override;
|
||||
|
||||
void dropDraggedItem(float mouseX, float mouseY);
|
||||
|
||||
private:
|
||||
MyGUI::ProgressBar *mHealth, *mMagicka, *mStamina, *mEnemyHealth, *mDrowning;
|
||||
MyGUI::Widget* mHealthFrame;
|
||||
|
|
|
|||
63
apps/openmw/mwgui/inventorytabsoverlay.cpp
Normal file
63
apps/openmw/mwgui/inventorytabsoverlay.cpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#include "inventorytabsoverlay.hpp"
|
||||
|
||||
#include <MyGUI_Button.h>
|
||||
#include <MyGUI_ImageBox.h>
|
||||
#include <MyGUI_Window.h>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
InventoryTabsOverlay::InventoryTabsOverlay()
|
||||
: WindowBase("openmw_inventory_tabs.layout")
|
||||
{
|
||||
MyGUI::Button* tab;
|
||||
static const char* kTabIds[] = { "TabMap", "TabInventory", "TabSpells", "TabStats" };
|
||||
|
||||
for (const char* id : kTabIds)
|
||||
{
|
||||
getWidget(tab, id);
|
||||
tab->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryTabsOverlay::onTabClicked);
|
||||
mTabs.push_back(tab);
|
||||
}
|
||||
|
||||
MyGUI::ImageBox* image;
|
||||
getWidget(image, "BtnL2Image");
|
||||
image->setImageTexture(
|
||||
MWBase::Environment::get().getInputManager()->getControllerAxisIcon(SDL_CONTROLLER_AXIS_TRIGGERLEFT));
|
||||
|
||||
getWidget(image, "BtnR2Image");
|
||||
image->setImageTexture(
|
||||
MWBase::Environment::get().getInputManager()->getControllerAxisIcon(SDL_CONTROLLER_AXIS_TRIGGERRIGHT));
|
||||
}
|
||||
|
||||
int InventoryTabsOverlay::getHeight()
|
||||
{
|
||||
MyGUI::Window* window = mMainWidget->castType<MyGUI::Window>();
|
||||
return window->getHeight();
|
||||
}
|
||||
|
||||
void InventoryTabsOverlay::onTabClicked(MyGUI::Widget* sender)
|
||||
{
|
||||
if (!MWBase::Environment::get().getWindowManager()->getJournalAllowed())
|
||||
return;
|
||||
|
||||
for (int i = 0; i < static_cast<int>(mTabs.size()); i++)
|
||||
{
|
||||
if (mTabs[i] == sender)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->setActiveControllerWindow(GM_Inventory, i);
|
||||
setTab(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryTabsOverlay::setTab(int index)
|
||||
{
|
||||
for (int i = 0; i < static_cast<int>(mTabs.size()); i++)
|
||||
mTabs[i]->setStateSelected(i == index);
|
||||
}
|
||||
}
|
||||
28
apps/openmw/mwgui/inventorytabsoverlay.hpp
Normal file
28
apps/openmw/mwgui/inventorytabsoverlay.hpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef MWGUI_INVENTORYTABSSOVERLAY_H
|
||||
#define MWGUI_INVENTORYTABSSOVERLAY_H
|
||||
|
||||
#include "windowbase.hpp"
|
||||
|
||||
namespace MyGUI
|
||||
{
|
||||
class Button;
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class InventoryTabsOverlay : public WindowBase
|
||||
{
|
||||
public:
|
||||
InventoryTabsOverlay();
|
||||
|
||||
int getHeight();
|
||||
void setTab(int index);
|
||||
|
||||
private:
|
||||
std::vector<MyGUI::Button*> mTabs;
|
||||
|
||||
void onTabClicked(MyGUI::Widget* sender);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
#include <components/settings/values.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
#include "../mwbase/luamanager.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
|
@ -31,13 +32,17 @@
|
|||
#include "../mwmechanics/actorutil.hpp"
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
|
||||
#include "companionwindow.hpp"
|
||||
#include "container.hpp"
|
||||
#include "countdialog.hpp"
|
||||
#include "draganddrop.hpp"
|
||||
#include "hud.hpp"
|
||||
#include "inventoryitemmodel.hpp"
|
||||
#include "itemtransfer.hpp"
|
||||
#include "itemview.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "sortfilteritemmodel.hpp"
|
||||
#include "statswindow.hpp"
|
||||
#include "tooltips.hpp"
|
||||
#include "tradeitemmodel.hpp"
|
||||
#include "tradewindow.hpp"
|
||||
|
|
@ -89,6 +94,7 @@ namespace MWGui
|
|||
, mPreview(std::make_unique<MWRender::InventoryPreview>(parent, resourceSystem, MWMechanics::getPlayer()))
|
||||
, mTrading(false)
|
||||
, mUpdateNextFrame(false)
|
||||
, mPendingControllerAction(ControllerAction::None)
|
||||
{
|
||||
mPreviewTexture
|
||||
= std::make_unique<MyGUIPlatform::OSGTexture>(mPreview->getTexture(), mPreview->getTextureStateSet());
|
||||
|
|
@ -129,6 +135,25 @@ namespace MWGui
|
|||
|
||||
setGuiMode(mGuiMode);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
// Show L1 and R1 buttons next to tabs
|
||||
MyGUI::ImageBox* image;
|
||||
getWidget(image, "BtnL1Image");
|
||||
image->setVisible(true);
|
||||
image->setUserString("Hidden", "false");
|
||||
image->setImageTexture(MWBase::Environment::get().getInputManager()->getControllerButtonIcon(
|
||||
SDL_CONTROLLER_BUTTON_LEFTSHOULDER));
|
||||
|
||||
getWidget(image, "BtnR1Image");
|
||||
image->setVisible(true);
|
||||
image->setUserString("Hidden", "false");
|
||||
image->setImageTexture(MWBase::Environment::get().getInputManager()->getControllerButtonIcon(
|
||||
SDL_CONTROLLER_BUTTON_RIGHTSHOULDER));
|
||||
|
||||
mControllerButtons.mR3 = "#{sInfo}";
|
||||
}
|
||||
|
||||
adjustPanes();
|
||||
}
|
||||
|
||||
|
|
@ -208,9 +233,13 @@ namespace MWGui
|
|||
|
||||
void InventoryWindow::setGuiMode(GuiMode mode)
|
||||
{
|
||||
if (Settings::gui().mControllerMenus && mGuiMode == mode && isVisible())
|
||||
return;
|
||||
|
||||
mGuiMode = mode;
|
||||
const WindowSettingValues settings = getModeSettings(mGuiMode);
|
||||
setPinButtonVisible(mode != GM_Container && mode != GM_Companion && mode != GM_Barter);
|
||||
setPinButtonVisible(
|
||||
mode != GM_Container && mode != GM_Companion && mode != GM_Barter && !Settings::gui().mControllerMenus);
|
||||
|
||||
const WindowRectSettingValues& rect = settings.mIsMaximized ? settings.mMaximized : settings.mRegular;
|
||||
|
||||
|
|
@ -306,18 +335,26 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
if (count > 1 && !shift)
|
||||
// Show a dialog to select a count of items, but not when using an item from the inventory
|
||||
// in controller mode. In that case, we skip the dialog and just use one item immediately.
|
||||
if (count > 1 && !shift && mPendingControllerAction != ControllerAction::Use)
|
||||
{
|
||||
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
|
||||
std::string message = mTrading ? "#{sQuanityMenuMessage01}" : "#{sTake}";
|
||||
std::string message = "#{sTake}";
|
||||
if (mTrading || mPendingControllerAction == ControllerAction::Sell)
|
||||
message = "#{sQuanityMenuMessage01}";
|
||||
else if (mPendingControllerAction == ControllerAction::Drop)
|
||||
message = "#{sDrop}";
|
||||
std::string name{ object.getClass().getName(object) };
|
||||
name += MWGui::ToolTips::getSoulString(object.getCellRef());
|
||||
dialog->openCountDialog(name, message, count);
|
||||
dialog->eventOkClicked.clear();
|
||||
|
||||
if (mTrading)
|
||||
if (mTrading || mPendingControllerAction == ControllerAction::Sell)
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::sellItem);
|
||||
else if (MyGUI::InputManager::getInstance().isAltPressed())
|
||||
else if (mPendingControllerAction == ControllerAction::Drop)
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::dropItem);
|
||||
else if (MyGUI::InputManager::getInstance().isAltPressed()
|
||||
|| mPendingControllerAction == ControllerAction::Transfer)
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::transferItem);
|
||||
else
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::dragItem);
|
||||
|
|
@ -328,13 +365,35 @@ namespace MWGui
|
|||
{
|
||||
mSelectedItem = index;
|
||||
|
||||
if (mTrading)
|
||||
if (mTrading || mPendingControllerAction == ControllerAction::Sell)
|
||||
sellItem(nullptr, count);
|
||||
else if (MyGUI::InputManager::getInstance().isAltPressed())
|
||||
else if (mPendingControllerAction == ControllerAction::Use)
|
||||
{
|
||||
dragItem(nullptr, count);
|
||||
if (item.mType == ItemStack::Type_Equipped)
|
||||
{
|
||||
// Drop the item on the inventory background to unequip it.
|
||||
onBackgroundSelected();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Drop the item on the avatar to activate or equip it.
|
||||
onAvatarClicked(nullptr);
|
||||
// Drop any remaining items back in inventory. This is needed when clicking on a
|
||||
// stack of items; we only want to use the first item.
|
||||
onBackgroundSelected();
|
||||
}
|
||||
}
|
||||
else if (mPendingControllerAction == ControllerAction::Drop)
|
||||
dropItem(nullptr, count);
|
||||
else if (MyGUI::InputManager::getInstance().isAltPressed()
|
||||
|| mPendingControllerAction == ControllerAction::Transfer)
|
||||
transferItem(nullptr, count);
|
||||
else
|
||||
dragItem(nullptr, count);
|
||||
}
|
||||
|
||||
mPendingControllerAction = ControllerAction::None;
|
||||
}
|
||||
|
||||
void InventoryWindow::ensureSelectedItemUnequipped(int count)
|
||||
|
|
@ -408,6 +467,19 @@ namespace MWGui
|
|||
notifyContentChanged();
|
||||
}
|
||||
|
||||
void InventoryWindow::dropItem(MyGUI::Widget* sender, size_t count)
|
||||
{
|
||||
if (mGuiMode != MWGui::GM_Inventory)
|
||||
return;
|
||||
|
||||
if (!mDragAndDrop->mIsOnDragAndDrop)
|
||||
dragItem(sender, count);
|
||||
|
||||
// Drop the item into the gameworld
|
||||
if (mDragAndDrop->mIsOnDragAndDrop)
|
||||
MWBase::Environment::get().getWindowManager()->getHud()->dropDraggedItem(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
void InventoryWindow::updateItemView()
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->updateSpellWindow();
|
||||
|
|
@ -523,7 +595,9 @@ namespace MWGui
|
|||
|
||||
void InventoryWindow::onTitleDoubleClicked()
|
||||
{
|
||||
if (MyGUI::InputManager::getInstance().isShiftPressed())
|
||||
if (Settings::gui().mControllerMenus && mGuiMode == GM_Inventory)
|
||||
return;
|
||||
else if (MyGUI::InputManager::getInstance().isShiftPressed())
|
||||
toggleMaximized();
|
||||
else if (!mPinned)
|
||||
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Inventory);
|
||||
|
|
@ -890,4 +964,151 @@ namespace MWGui
|
|||
const MyGUI::IntSize viewport = getPreviewViewportSize();
|
||||
return osg::Vec2f(normalisedX * float(viewport.width - 1), (1.0 - normalisedY) * float(viewport.height - 1));
|
||||
}
|
||||
|
||||
ControllerButtons* InventoryWindow::getControllerButtons()
|
||||
{
|
||||
switch (mGuiMode)
|
||||
{
|
||||
case MWGui::GM_Companion:
|
||||
mControllerButtons.mA = "#{OMWEngine:InventorySelect}";
|
||||
mControllerButtons.mB = "#{Interface:Close}";
|
||||
mControllerButtons.mX.clear();
|
||||
mControllerButtons.mR2 = "#{sCompanionShare}";
|
||||
break;
|
||||
case MWGui::GM_Container:
|
||||
mControllerButtons.mA = "#{OMWEngine:InventorySelect}";
|
||||
mControllerButtons.mB = "#{Interface:Close}";
|
||||
mControllerButtons.mX = "#{sTakeAll}";
|
||||
mControllerButtons.mR2 = "#{sContainer}";
|
||||
break;
|
||||
case MWGui::GM_Barter:
|
||||
mControllerButtons.mA = "#{sSell}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
mControllerButtons.mX = "#{sOffer}";
|
||||
mControllerButtons.mR2 = "#{sBarter}";
|
||||
break;
|
||||
case MWGui::GM_Inventory:
|
||||
default:
|
||||
mControllerButtons.mA = "#{sEquip}";
|
||||
mControllerButtons.mB = "#{sBack}";
|
||||
mControllerButtons.mX = "#{sDrop}";
|
||||
mControllerButtons.mR2.clear();
|
||||
break;
|
||||
}
|
||||
return &mControllerButtons;
|
||||
}
|
||||
|
||||
bool InventoryWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
mPendingControllerAction = ControllerAction::None; // Clear any pending controller actions
|
||||
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mGuiMode == MWGui::GM_Inventory)
|
||||
mPendingControllerAction = ControllerAction::Use;
|
||||
else if (mGuiMode == MWGui::GM_Companion || mGuiMode == MWGui::GM_Container)
|
||||
mPendingControllerAction = ControllerAction::Transfer;
|
||||
else if (mGuiMode == MWGui::GM_Barter)
|
||||
mPendingControllerAction = ControllerAction::Sell;
|
||||
|
||||
mItemView->onControllerButton(SDL_CONTROLLER_BUTTON_A);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
{
|
||||
if (mGuiMode == MWGui::GM_Inventory)
|
||||
{
|
||||
mPendingControllerAction = ControllerAction::Drop;
|
||||
mItemView->onControllerButton(SDL_CONTROLLER_BUTTON_A);
|
||||
}
|
||||
else if (mGuiMode == MWGui::GM_Container)
|
||||
{
|
||||
// Take all. Pass the button press to the container window and let it do the
|
||||
// logic of taking all.
|
||||
MWGui::ContainerWindow* containerWindow = static_cast<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 = static_cast<MWGui::TradeWindow*>(
|
||||
MWBase::Environment::get().getWindowManager()->getGuiModeWindows(mGuiMode).at(1));
|
||||
tradeWindow->onControllerButtonEvent(arg);
|
||||
}
|
||||
}
|
||||
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);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
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);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else
|
||||
{
|
||||
mItemView->onControllerButton(arg.button);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void InventoryWindow::setActiveControllerWindow(bool active)
|
||||
{
|
||||
if (!Settings::gui().mControllerMenus)
|
||||
return;
|
||||
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
if (winMgr->getMode() == MWGui::GM_Inventory)
|
||||
{
|
||||
// Fill the screen, or limit to a certain size on large screens. Size chosen to
|
||||
// match the size of the stats window.
|
||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
int width = std::min(viewSize.width, 1600);
|
||||
int height = std::min(winMgr->getControllerMenuHeight(), StatsWindow::getIdealHeight());
|
||||
int x = (viewSize.width - width) / 2;
|
||||
int y = (viewSize.height - height) / 2;
|
||||
|
||||
MyGUI::Window* window = mMainWidget->castType<MyGUI::Window>();
|
||||
window->setCoord(x, active ? y : viewSize.height + 1, width, height);
|
||||
|
||||
adjustPanes();
|
||||
updatePreviewSize();
|
||||
}
|
||||
|
||||
// Show L1 and R1 buttons next to tabs
|
||||
MyGUI::Widget* image;
|
||||
getWidget(image, "BtnL1Image");
|
||||
image->setVisible(active);
|
||||
|
||||
getWidget(image, "BtnR1Image");
|
||||
image->setVisible(active);
|
||||
|
||||
mItemView->setActiveControllerWindow(active);
|
||||
WindowBase::setActiveControllerWindow(active);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,8 +77,12 @@ namespace MWGui
|
|||
|
||||
std::string_view getWindowIdForLua() const override { return "Inventory"; }
|
||||
|
||||
ControllerButtons* getControllerButtons() override;
|
||||
|
||||
protected:
|
||||
void onTitleDoubleClicked() override;
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
void setActiveControllerWindow(bool active) override;
|
||||
|
||||
private:
|
||||
Misc::NotNullPtr<DragAndDrop> mDragAndDrop;
|
||||
|
|
@ -126,9 +130,20 @@ namespace MWGui
|
|||
|
||||
void onBackgroundSelected();
|
||||
|
||||
enum class ControllerAction
|
||||
{
|
||||
None,
|
||||
Use,
|
||||
Transfer,
|
||||
Sell,
|
||||
Drop,
|
||||
};
|
||||
ControllerAction mPendingControllerAction;
|
||||
|
||||
void sellItem(MyGUI::Widget* sender, std::size_t count);
|
||||
void dragItem(MyGUI::Widget* sender, std::size_t count);
|
||||
void transferItem(MyGUI::Widget* sender, std::size_t count);
|
||||
void dropItem(MyGUI::Widget* sender, std::size_t count);
|
||||
|
||||
void onWindowResize(MyGUI::Window* _sender);
|
||||
void onFilterChanged(MyGUI::Widget* _sender);
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
#include "itemchargeview.hpp"
|
||||
|
||||
#include <SDL_gamecontroller.h>
|
||||
#include <set>
|
||||
|
||||
#include <MyGUI_FactoryManager.h>
|
||||
#include <MyGUI_Gui.h>
|
||||
#include <MyGUI_ScrollView.h>
|
||||
#include <MyGUI_TextBox.h>
|
||||
#include <MyGUI_UString.h>
|
||||
|
||||
#include <components/esm3/loadench.hpp>
|
||||
#include <components/settings/values.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include "../mwmechanics/spellutil.hpp"
|
||||
|
||||
|
|
@ -19,6 +20,8 @@
|
|||
|
||||
#include "itemmodel.hpp"
|
||||
#include "itemwidget.hpp"
|
||||
#include "textcolours.hpp"
|
||||
#include "windowbase.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
|
@ -156,11 +159,20 @@ namespace MWGui
|
|||
mScrollView->setCanvasSize(
|
||||
MyGUI::IntSize(mScrollView->getWidth(), std::max(mScrollView->getHeight(), currentY)));
|
||||
mScrollView->setVisibleVScroll(true);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
updateControllerFocus(-1, mControllerFocus);
|
||||
}
|
||||
|
||||
void ItemChargeView::resetScrollbars()
|
||||
{
|
||||
mScrollView->setViewOffset(MyGUI::IntPoint(0, 0));
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
updateControllerFocus(mControllerFocus, 0);
|
||||
mControllerFocus = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ItemChargeView::setSize(const MyGUI::IntSize& value)
|
||||
|
|
@ -224,4 +236,52 @@ namespace MWGui
|
|||
mScrollView->setViewOffset(
|
||||
MyGUI::IntPoint(0, static_cast<int>(mScrollView->getViewOffset().top + rel * 0.3f)));
|
||||
}
|
||||
|
||||
void ItemChargeView::onControllerButton(const unsigned char button)
|
||||
{
|
||||
if (mLines.empty())
|
||||
return;
|
||||
|
||||
int prevFocus = mControllerFocus;
|
||||
|
||||
if (button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
// Select the focused item, if any.
|
||||
if (mControllerFocus >= 0 && mControllerFocus < static_cast<int>(mLines.size()))
|
||||
onIconClicked(mLines[mControllerFocus].mIcon);
|
||||
}
|
||||
else if (button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
mControllerFocus = wrap(mControllerFocus - 1, mLines.size());
|
||||
else if (button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
mControllerFocus = wrap(mControllerFocus + 1, mLines.size());
|
||||
|
||||
if (prevFocus != mControllerFocus)
|
||||
updateControllerFocus(prevFocus, mControllerFocus);
|
||||
}
|
||||
|
||||
void ItemChargeView::updateControllerFocus(int prevFocus, int newFocus)
|
||||
{
|
||||
if (mLines.empty())
|
||||
return;
|
||||
|
||||
const TextColours& textColours{ MWBase::Environment::get().getWindowManager()->getTextColours() };
|
||||
|
||||
if (prevFocus >= 0 && prevFocus < static_cast<int>(mLines.size()))
|
||||
{
|
||||
mLines[prevFocus].mText->setTextColour(textColours.normal);
|
||||
mLines[prevFocus].mIcon->setControllerFocus(false);
|
||||
}
|
||||
|
||||
if (newFocus >= 0 && newFocus < static_cast<int>(mLines.size()))
|
||||
{
|
||||
mLines[newFocus].mText->setTextColour(textColours.link);
|
||||
mLines[newFocus].mIcon->setControllerFocus(true);
|
||||
|
||||
// Scroll the list to keep the active item in view
|
||||
if (newFocus <= 3)
|
||||
mScrollView->setViewOffset(MyGUI::IntPoint(0, 0));
|
||||
else
|
||||
mScrollView->setViewOffset(MyGUI::IntPoint(0, -55 * (newFocus - 3)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ namespace MWGui
|
|||
|
||||
MyGUI::delegates::MultiDelegate<MyGUI::Widget*, const MWWorld::Ptr&> eventItemClicked;
|
||||
|
||||
void onControllerButton(const unsigned char button);
|
||||
|
||||
private:
|
||||
struct Line
|
||||
{
|
||||
|
|
@ -72,6 +74,9 @@ namespace MWGui
|
|||
std::unique_ptr<ItemModel> mModel;
|
||||
MyGUI::ScrollView* mScrollView;
|
||||
DisplayMode mDisplayMode;
|
||||
|
||||
int mControllerFocus;
|
||||
void updateControllerFocus(int prevFocus, int newFocus);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include <MyGUI_Button.h>
|
||||
#include <MyGUI_TextBox.h>
|
||||
|
||||
#include <components/settings/values.hpp>
|
||||
|
||||
#include "inventoryitemmodel.hpp"
|
||||
#include "itemview.hpp"
|
||||
#include "sortfilteritemmodel.hpp"
|
||||
|
|
@ -26,6 +28,10 @@ namespace MWGui
|
|||
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ItemSelectionDialog::onCancelButtonClicked);
|
||||
|
||||
center();
|
||||
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
mControllerButtons.mR3 = "#{sInfo}";
|
||||
}
|
||||
|
||||
bool ItemSelectionDialog::exit()
|
||||
|
|
@ -40,6 +46,8 @@ namespace MWGui
|
|||
mSortModel = sortModel.get();
|
||||
mItemView->setModel(std::move(sortModel));
|
||||
mItemView->resetScrollBars();
|
||||
if (Settings::gui().mControllerMenus)
|
||||
mItemView->setActiveControllerWindow(true);
|
||||
}
|
||||
|
||||
void ItemSelectionDialog::setCategory(int category)
|
||||
|
|
@ -65,4 +73,13 @@ namespace MWGui
|
|||
exit();
|
||||
}
|
||||
|
||||
bool ItemSelectionDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
onCancelButtonClicked(nullptr);
|
||||
else
|
||||
mItemView->onControllerButton(arg.button);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ namespace MWGui
|
|||
void onSelectedItem(int index);
|
||||
|
||||
void onCancelButtonClicked(MyGUI::Widget* sender);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@
|
|||
#include <MyGUI_ImageBox.h>
|
||||
#include <MyGUI_ScrollView.h>
|
||||
|
||||
#include <components/settings/values.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include "itemmodel.hpp"
|
||||
#include "itemwidget.hpp"
|
||||
|
||||
|
|
@ -15,6 +21,7 @@ namespace MWGui
|
|||
|
||||
ItemView::ItemView()
|
||||
: mScrollView(nullptr)
|
||||
, mControllerActiveWindow(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -46,13 +53,16 @@ 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 = std::max(maxHeight / 42, 1);
|
||||
mItemCount = dragArea->getChildCount();
|
||||
bool showScrollbar = static_cast<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 < dragArea->getChildCount(); ++i)
|
||||
for (int i = 0; i < mItemCount; ++i)
|
||||
{
|
||||
MyGUI::Widget* w = dragArea->getChildAt(i);
|
||||
|
||||
|
|
@ -60,7 +70,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 +80,12 @@ namespace MWGui
|
|||
|
||||
MyGUI::IntSize size = MyGUI::IntSize(std::max(mScrollView->getSize().width, x), mScrollView->getSize().height);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerFocus = std::clamp(mControllerFocus, 0, 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 +138,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 +186,108 @@ namespace MWGui
|
|||
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::ItemView>("Widget");
|
||||
}
|
||||
|
||||
void ItemView::setActiveControllerWindow(bool active)
|
||||
{
|
||||
mControllerActiveWindow = active;
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setControllerTooltip(
|
||||
active && Settings::gui().mControllerTooltips);
|
||||
|
||||
if (active)
|
||||
updateControllerFocus(-1, mControllerFocus);
|
||||
else
|
||||
updateControllerFocus(mControllerFocus, -1);
|
||||
}
|
||||
|
||||
void ItemView::onControllerButton(const unsigned char button)
|
||||
{
|
||||
if (!mItemCount)
|
||||
return;
|
||||
|
||||
int prevFocus = mControllerFocus;
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case SDL_CONTROLLER_BUTTON_A:
|
||||
// Select the focused item, if any.
|
||||
if (mControllerFocus >= 0 && mControllerFocus < mItemCount)
|
||||
{
|
||||
MyGUI::Widget* dragArea = mScrollView->getChildAt(0);
|
||||
onSelectedItem(dragArea->getChildAt(mControllerFocus));
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
|
||||
// Toggle info tooltip
|
||||
MWBase::Environment::get().getWindowManager()->setControllerTooltip(
|
||||
!MWBase::Environment::get().getWindowManager()->getControllerTooltip());
|
||||
updateControllerFocus(-1, mControllerFocus);
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_UP:
|
||||
if (mControllerFocus % mRows == 0)
|
||||
mControllerFocus = std::min(mControllerFocus + mRows - 1, mItemCount - 1);
|
||||
else
|
||||
mControllerFocus--;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
|
||||
if (mControllerFocus % mRows == mRows - 1 || mControllerFocus == mItemCount - 1)
|
||||
mControllerFocus -= mControllerFocus % mRows;
|
||||
else
|
||||
mControllerFocus++;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
|
||||
if (mControllerFocus >= mRows)
|
||||
mControllerFocus -= mRows;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
|
||||
if (mControllerFocus + mRows < mItemCount)
|
||||
mControllerFocus += mRows;
|
||||
else if (mControllerFocus / mRows != (mItemCount - 1) / mRows)
|
||||
mControllerFocus = mItemCount - 1;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (prevFocus != mControllerFocus)
|
||||
updateControllerFocus(prevFocus, mControllerFocus);
|
||||
else
|
||||
updateControllerFocus(-1, mControllerFocus);
|
||||
}
|
||||
|
||||
void ItemView::updateControllerFocus(int prevFocus, int newFocus)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->setCursorVisible(
|
||||
!MWBase::Environment::get().getWindowManager()->getControllerTooltip());
|
||||
|
||||
if (!mItemCount)
|
||||
return;
|
||||
|
||||
MyGUI::Widget* dragArea = mScrollView->getChildAt(0);
|
||||
|
||||
if (prevFocus >= 0 && prevFocus < mItemCount)
|
||||
{
|
||||
ItemWidget* prev = static_cast<ItemWidget*>(dragArea->getChildAt(prevFocus));
|
||||
if (prev)
|
||||
prev->setControllerFocus(false);
|
||||
}
|
||||
|
||||
if (mControllerActiveWindow && newFocus >= 0 && newFocus < mItemCount)
|
||||
{
|
||||
ItemWidget* focused = static_cast<ItemWidget*>(dragArea->getChildAt(newFocus));
|
||||
if (focused)
|
||||
{
|
||||
focused->setControllerFocus(true);
|
||||
|
||||
// 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));
|
||||
|
||||
if (MWBase::Environment::get().getWindowManager()->getControllerTooltip())
|
||||
MWBase::Environment::get().getInputManager()->warpMouseToWidget(focused);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ namespace MWGui
|
|||
|
||||
void resetScrollBars();
|
||||
|
||||
void setActiveControllerWindow(bool active);
|
||||
int getControllerFocus() { return mControllerFocus; }
|
||||
int getItemCount() { return mItemCount; }
|
||||
void onControllerButton(const unsigned char button);
|
||||
|
||||
private:
|
||||
void initialiseOverride() override;
|
||||
|
||||
|
|
@ -47,6 +52,12 @@ namespace MWGui
|
|||
|
||||
std::unique_ptr<ItemModel> mModel;
|
||||
MyGUI::ScrollView* mScrollView;
|
||||
|
||||
int mItemCount = 0;
|
||||
int mRows;
|
||||
int mControllerFocus = 0;
|
||||
bool mControllerActiveWindow;
|
||||
void updateControllerFocus(int prevFocus, int newFocus);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -156,6 +156,13 @@ namespace MWGui
|
|||
return MWGui::BookTypesetter::Utf8Span(begin, begin + text.length());
|
||||
}
|
||||
|
||||
int getCyrillicIndexPageCount()
|
||||
{
|
||||
// For small font size split alphabet to two columns (2x15 characers), for big font size split it to three
|
||||
// colums (3x10 characters).
|
||||
return Settings::gui().mFontSize < 18 ? 2 : 3;
|
||||
}
|
||||
|
||||
typedef TypesetBook::Ptr book;
|
||||
|
||||
JournalBooks::JournalBooks(JournalViewModel::Ptr model, ToUTF8::FromType encoding)
|
||||
|
|
@ -169,7 +176,7 @@ namespace MWGui
|
|||
{
|
||||
BookTypesetter::Ptr typesetter = createTypesetter();
|
||||
|
||||
BookTypesetter::Style* header = typesetter->createStyle({}, MyGUI::Colour(0.60f, 0.00f, 0.00f));
|
||||
BookTypesetter::Style* header = typesetter->createStyle({}, journalHeaderColour);
|
||||
BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black);
|
||||
|
||||
typesetter->write(header, to_utf8_span("You have no journal entries!"));
|
||||
|
|
@ -184,7 +191,7 @@ namespace MWGui
|
|||
{
|
||||
BookTypesetter::Ptr typesetter = createTypesetter();
|
||||
|
||||
BookTypesetter::Style* header = typesetter->createStyle({}, MyGUI::Colour(0.60f, 0.00f, 0.00f));
|
||||
BookTypesetter::Style* header = typesetter->createStyle({}, journalHeaderColour);
|
||||
BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black);
|
||||
|
||||
mModel->visitJournalEntries({}, AddJournalEntry(typesetter, body, header, true));
|
||||
|
|
@ -196,7 +203,7 @@ namespace MWGui
|
|||
{
|
||||
BookTypesetter::Ptr typesetter = createTypesetter();
|
||||
|
||||
BookTypesetter::Style* header = typesetter->createStyle({}, MyGUI::Colour(0.60f, 0.00f, 0.00f));
|
||||
BookTypesetter::Style* header = typesetter->createStyle({}, journalHeaderColour);
|
||||
BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black);
|
||||
|
||||
mModel->visitTopicName(topicId, AddTopicName(typesetter, header));
|
||||
|
|
@ -212,7 +219,7 @@ namespace MWGui
|
|||
{
|
||||
BookTypesetter::Ptr typesetter = createTypesetter();
|
||||
|
||||
BookTypesetter::Style* header = typesetter->createStyle({}, MyGUI::Colour(0.60f, 0.00f, 0.00f));
|
||||
BookTypesetter::Style* header = typesetter->createStyle({}, journalHeaderColour);
|
||||
BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black);
|
||||
|
||||
AddQuestName addName(typesetter, header);
|
||||
|
|
@ -277,13 +284,8 @@ namespace MWGui
|
|||
|
||||
// for small font size split alphabet to two columns (2x15 characers), for big font size split it to three
|
||||
// colums (3x10 characters).
|
||||
int sectionBreak = 10;
|
||||
mIndexPagesCount = 3;
|
||||
if (Settings::gui().mFontSize < 18)
|
||||
{
|
||||
sectionBreak = 15;
|
||||
mIndexPagesCount = 2;
|
||||
}
|
||||
mIndexPagesCount = getCyrillicIndexPageCount();
|
||||
int sectionBreak = 30 / mIndexPagesCount;
|
||||
|
||||
unsigned char ch[3] = { 0xd0, 0x90, 0x00 }; // CYRILLIC CAPITAL A is a 0xd090 in UTF-8
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@
|
|||
namespace MWGui
|
||||
{
|
||||
MWGui::BookTypesetter::Utf8Span to_utf8_span(std::string_view text);
|
||||
int getCyrillicIndexPageCount();
|
||||
|
||||
const MyGUI::Colour journalHeaderColour = MyGUI::Colour(0.60f, 0.00f, 0.00f);
|
||||
|
||||
struct JournalBooks
|
||||
{
|
||||
|
|
|
|||
|
|
@ -218,6 +218,16 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
// Latin = 26 (13 + 13)
|
||||
mIndexRowCount = 13;
|
||||
bool isRussian = (mEncoding == ToUTF8::WINDOWS_1251);
|
||||
if (isRussian) // Cyrillic is either (10 + 10 + 10) or (15 + 15)
|
||||
mIndexRowCount = MWGui::getCyrillicIndexPageCount();
|
||||
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mX = "#{OMWEngine:JournalQuests}";
|
||||
mControllerButtons.mY = "#{sTopics}";
|
||||
|
||||
mQuestMode = false;
|
||||
mAllQuests = false;
|
||||
mOptionsMode = false;
|
||||
|
|
@ -248,6 +258,9 @@ namespace
|
|||
}
|
||||
updateShowingPages();
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
setControllerFocusedQuest(0);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(getWidget<MyGUI::Widget>(CloseBTN));
|
||||
}
|
||||
|
||||
|
|
@ -275,6 +288,8 @@ namespace
|
|||
|
||||
updateShowingPages();
|
||||
updateCloseJournalButton();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
|
||||
}
|
||||
|
||||
void setOptionsMode()
|
||||
|
|
@ -307,6 +322,8 @@ namespace
|
|||
notifyQuests(getWidget<MyGUI::Widget>(QuestsList));
|
||||
else
|
||||
notifyTopics(getWidget<MyGUI::Widget>(TopicsList));
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
|
||||
}
|
||||
|
||||
void pushBook(Book& book, unsigned int page)
|
||||
|
|
@ -338,6 +355,7 @@ namespace
|
|||
{
|
||||
setVisible(CloseBTN, mStates.size() < 2);
|
||||
setVisible(JournalBTN, mStates.size() >= 2);
|
||||
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
|
||||
}
|
||||
|
||||
void updateShowingPages()
|
||||
|
|
@ -380,6 +398,8 @@ namespace
|
|||
|
||||
setText(PageOneNum, page + 1);
|
||||
setText(PageTwoNum, page + 2);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
|
||||
}
|
||||
|
||||
void notifyKeyPress(MyGUI::Widget* sender, MyGUI::KeyCode key, MyGUI::Char character)
|
||||
|
|
@ -407,6 +427,7 @@ namespace
|
|||
mTopicsMode = false;
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
|
||||
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
|
||||
}
|
||||
|
||||
void notifyTopicSelected(const std::string& topicIdString, int id)
|
||||
|
|
@ -439,6 +460,7 @@ namespace
|
|||
mOptionsMode = false;
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
|
||||
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
|
||||
}
|
||||
|
||||
void notifyOptions(MyGUI::Widget* _sender)
|
||||
|
|
@ -459,6 +481,9 @@ namespace
|
|||
getPage(LeftTopicIndex)->showPage(mTopicIndexBook, 0);
|
||||
getPage(RightTopicIndex)->showPage(mTopicIndexBook, 1);
|
||||
}
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
setIndexControllerFocus(true);
|
||||
}
|
||||
|
||||
void notifyJournal(MyGUI::Widget* _sender)
|
||||
|
|
@ -467,6 +492,22 @@ namespace
|
|||
popBook();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
|
||||
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
|
||||
}
|
||||
|
||||
void addControllerButtons(Gui::MWList* _list, size_t _selectedIndex)
|
||||
{
|
||||
mButtons.clear();
|
||||
for (size_t i = 0; i < _list->getItemCount(); i++)
|
||||
{
|
||||
MyGUI::Button* listItem = _list->getItemWidget(_list->getItemNameAt(i));
|
||||
if (listItem)
|
||||
{
|
||||
listItem->setTextColour(
|
||||
mButtons.size() == _selectedIndex ? MWGui::journalHeaderColour : MyGUI::Colour::Black);
|
||||
mButtons.push_back(listItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void notifyIndexLinkClicked(MWGui::TypesetBook::InteractiveId index)
|
||||
|
|
@ -487,7 +528,14 @@ namespace
|
|||
|
||||
list->adjustSize();
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
setControllerFocusedQuest(0);
|
||||
addControllerButtons(list, mSelectedQuest);
|
||||
}
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
|
||||
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
|
||||
}
|
||||
|
||||
void notifyTopics(MyGUI::Widget* _sender)
|
||||
|
|
@ -503,6 +551,7 @@ namespace
|
|||
setVisible(ShowActiveBTN, false);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
|
||||
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
|
||||
}
|
||||
|
||||
struct AddNamesToList
|
||||
|
|
@ -554,6 +603,12 @@ namespace
|
|||
list->sort();
|
||||
list->adjustSize();
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
addControllerButtons(list, mSelectedQuest);
|
||||
setControllerFocusedQuest(MWGui::wrap(mSelectedQuest, mButtons.size()));
|
||||
}
|
||||
|
||||
if (mAllQuests)
|
||||
{
|
||||
SetNamesInactive setInactive(list);
|
||||
|
|
@ -561,6 +616,7 @@ namespace
|
|||
}
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
|
||||
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
|
||||
}
|
||||
|
||||
void notifyShowAll(MyGUI::Widget* _sender)
|
||||
|
|
@ -639,6 +695,240 @@ namespace
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
MWGui::ControllerButtons* getControllerButtons() override
|
||||
{
|
||||
mControllerButtons.mB = mOptionsMode || mStates.size() > 1 ? "#{sBack}" : "#{Interface:Close}";
|
||||
mControllerButtons.mL1 = mOptionsMode ? "" : "#{sPrev}";
|
||||
mControllerButtons.mR1 = mOptionsMode ? "" : "#{sNext}";
|
||||
mControllerButtons.mR3 = mOptionsMode && mQuestMode ? "#{OMWEngine:JournalShowAll}" : "";
|
||||
return &mControllerButtons;
|
||||
}
|
||||
|
||||
void setIndexControllerFocus(bool focused)
|
||||
{
|
||||
int col = mSelectedIndex / mIndexRowCount;
|
||||
int row = mSelectedIndex % mIndexRowCount;
|
||||
mTopicIndexBook->setColour(col, row, 0, focused ? MWGui::journalHeaderColour : MyGUI::Colour::Black);
|
||||
}
|
||||
|
||||
void moveSelectedIndex(int offset)
|
||||
{
|
||||
setIndexControllerFocus(false);
|
||||
|
||||
int numChars = mEncoding == ToUTF8::WINDOWS_1251 ? 30 : 26;
|
||||
int col = mSelectedIndex / mIndexRowCount;
|
||||
|
||||
if (offset == -1) // Up
|
||||
{
|
||||
if (mSelectedIndex % mIndexRowCount == 0)
|
||||
mSelectedIndex = (col * mIndexRowCount) + mIndexRowCount - 1;
|
||||
else
|
||||
mSelectedIndex--;
|
||||
}
|
||||
else if (offset == 1) // Down
|
||||
{
|
||||
if (mSelectedIndex % mIndexRowCount == mIndexRowCount - 1)
|
||||
mSelectedIndex = col * mIndexRowCount;
|
||||
else
|
||||
mSelectedIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// mSelectedIndex is unsigned, so we have to be careful with our math.
|
||||
if (offset < 0)
|
||||
offset += numChars;
|
||||
|
||||
mSelectedIndex = (mSelectedIndex + offset) % numChars;
|
||||
}
|
||||
|
||||
setIndexControllerFocus(true);
|
||||
setText(PageOneNum, 1); // Redraw the list
|
||||
}
|
||||
|
||||
bool optionsModeButtonHandler(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A) // A: Mouse click or Select
|
||||
{
|
||||
if (mQuestMode)
|
||||
{
|
||||
// Choose a quest
|
||||
Gui::MWList* list = getWidget<Gui::MWList>(QuestsList);
|
||||
if (mSelectedQuest < list->getItemCount())
|
||||
notifyQuestClicked(list->getItemNameAt(mSelectedQuest), 0);
|
||||
}
|
||||
else if (mTopicsMode)
|
||||
{
|
||||
// Choose a topic
|
||||
Gui::MWList* list = getWidget<Gui::MWList>(TopicsList);
|
||||
if (mSelectedQuest < list->getItemCount())
|
||||
notifyTopicSelected(list->getItemNameAt(mSelectedQuest), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Choose an index. Cyrillic capital A is a 0xd090 in UTF-8.
|
||||
// Words can not be started with characters 26 or 28.
|
||||
int russianOffset = 0xd090;
|
||||
if (mSelectedIndex >= 26)
|
||||
russianOffset++;
|
||||
if (mSelectedIndex >= 27)
|
||||
russianOffset++; // 27, not 28, because of skipping char 26
|
||||
bool isRussian = (mEncoding == ToUTF8::WINDOWS_1251);
|
||||
notifyIndexLinkClicked(isRussian ? mSelectedIndex + russianOffset : mSelectedIndex + 'A');
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B) // B: Back
|
||||
{
|
||||
// Hide the options overlay
|
||||
notifyCancel(getWidget<MyGUI::Widget>(CancelBTN));
|
||||
mQuestMode = false;
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X) // X: Quests
|
||||
{
|
||||
if (mQuestMode)
|
||||
{
|
||||
// Hide the quest overlay if visible
|
||||
notifyCancel(getWidget<MyGUI::Widget>(CancelBTN));
|
||||
mQuestMode = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show the quest overlay if viewing the topics list
|
||||
notifyQuests(getWidget<MyGUI::Widget>(QuestsBTN));
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_Y) // Y: Topics
|
||||
{
|
||||
if (!mQuestMode)
|
||||
{
|
||||
// Hide the topics overlay if visible
|
||||
notifyCancel(getWidget<MyGUI::Widget>(CancelBTN));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show the topics overlay if viewing the quest list
|
||||
notifyTopics(getWidget<MyGUI::Widget>(TopicsBTN));
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSTICK && mQuestMode) // R3: Show All/Some
|
||||
{
|
||||
if (mAllQuests)
|
||||
notifyShowActive(getWidget<MyGUI::Widget>(ShowActiveBTN));
|
||||
else
|
||||
notifyShowAll(getWidget<MyGUI::Widget>(ShowAllBTN));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
if (mQuestMode || mTopicsMode)
|
||||
{
|
||||
if (mButtons.size() <= 1)
|
||||
return true;
|
||||
|
||||
// Scroll through the list of quests or topics
|
||||
setControllerFocusedQuest(MWGui::wrap(mSelectedQuest - 1, mButtons.size()));
|
||||
}
|
||||
else
|
||||
moveSelectedIndex(-1);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
if (mQuestMode || mTopicsMode)
|
||||
{
|
||||
if (mButtons.size() <= 1)
|
||||
return true;
|
||||
|
||||
// Scroll through the list of quests or topics
|
||||
setControllerFocusedQuest(MWGui::wrap(mSelectedQuest + 1, mButtons.size()));
|
||||
}
|
||||
else
|
||||
moveSelectedIndex(1);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT && !mQuestMode && !mTopicsMode)
|
||||
moveSelectedIndex(-mIndexRowCount);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT && !mQuestMode && !mTopicsMode)
|
||||
moveSelectedIndex(mIndexRowCount);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER && (mQuestMode || mTopicsMode))
|
||||
{
|
||||
// Scroll up 5 items in the list of quests or topics
|
||||
setControllerFocusedQuest(std::max(static_cast<int>(mSelectedQuest) - 5, 0));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER && (mQuestMode || mTopicsMode))
|
||||
{
|
||||
// Scroll down 5 items in the list of quests or topics
|
||||
setControllerFocusedQuest(std::min(mSelectedQuest + 5, mButtons.size() - 1));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override
|
||||
{
|
||||
// If the topics or quest list is open, it should handle the buttons.
|
||||
if (mOptionsMode)
|
||||
return optionsModeButtonHandler(arg);
|
||||
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
return false;
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B) // B: Back
|
||||
{
|
||||
if (mStates.size() > 1)
|
||||
{
|
||||
// Pop the current book. If in quest mode, reopen the quest list.
|
||||
notifyJournal(getWidget<MyGUI::Widget>(JournalBTN));
|
||||
if (mQuestMode)
|
||||
{
|
||||
notifyOptions(getWidget<MyGUI::Widget>(OptionsBTN));
|
||||
notifyQuests(getWidget<MyGUI::Widget>(QuestsBTN));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Close the journal window
|
||||
notifyClose(getWidget<MyGUI::Widget>(CloseBTN));
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X) // X: Quests
|
||||
{
|
||||
// Show the quest overlay
|
||||
notifyOptions(getWidget<MyGUI::Widget>(OptionsBTN));
|
||||
if (!mQuestMode)
|
||||
notifyQuests(getWidget<MyGUI::Widget>(QuestsBTN));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_Y) // Y: Topics
|
||||
{
|
||||
// Show the topics overlay
|
||||
notifyOptions(getWidget<MyGUI::Widget>(OptionsBTN));
|
||||
if (mQuestMode)
|
||||
notifyTopics(getWidget<MyGUI::Widget>(TopicsBTN));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT || arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
|
||||
notifyPrevPage(getWidget<MyGUI::Widget>(PrevPageBTN));
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT
|
||||
|| arg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
|
||||
notifyNextPage(getWidget<MyGUI::Widget>(NextPageBTN));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void setControllerFocusedQuest(size_t index)
|
||||
{
|
||||
size_t listSize = mButtons.size();
|
||||
if (mSelectedQuest < listSize)
|
||||
mButtons[mSelectedQuest]->setTextColour(MyGUI::Colour::Black);
|
||||
|
||||
mSelectedQuest = index;
|
||||
if (mSelectedQuest < listSize)
|
||||
{
|
||||
mButtons[mSelectedQuest]->setTextColour(MWGui::journalHeaderColour);
|
||||
|
||||
// Scroll the list to keep the active item in view
|
||||
Gui::MWList* list = getWidget<Gui::MWList>(mQuestMode ? QuestsList : TopicsList);
|
||||
int offset = 0;
|
||||
for (int i = 4; i < static_cast<int>(mSelectedQuest); i++)
|
||||
offset += mButtons[i]->getHeight();
|
||||
list->setViewOffset(-offset);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,16 @@ namespace MWGui
|
|||
void setVisible(bool newValue) override = 0;
|
||||
|
||||
std::string_view getWindowIdForLua() const override { return "Journal"; }
|
||||
|
||||
size_t mIndexRowCount;
|
||||
|
||||
std::vector<MyGUI::Button*> mButtons;
|
||||
size_t mSelectedQuest = 0;
|
||||
size_t mSelectedIndex = 0;
|
||||
void moveSelectedIndex(int offset);
|
||||
void setIndexControllerFocus(bool focused);
|
||||
void setControllerFocusedQuest(size_t index);
|
||||
bool optionsModeButtonHandler(const SDL_ControllerButtonEvent& arg);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <MyGUI_UString.h>
|
||||
|
||||
#include <components/fallback/fallback.hpp>
|
||||
#include <components/settings/values.hpp>
|
||||
#include <components/widgets/box.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
|
@ -48,13 +49,12 @@ namespace MWGui
|
|||
|
||||
{
|
||||
const auto& store = MWBase::Environment::get().getESMStore()->get<ESM::Attribute>();
|
||||
const size_t perCol
|
||||
= static_cast<size_t>(std::ceil(store.getSize() / static_cast<float>(std::size(sColumnOffsets))));
|
||||
mPerCol = static_cast<size_t>(std::ceil(store.getSize() / static_cast<float>(std::size(sColumnOffsets))));
|
||||
size_t i = 0;
|
||||
for (const ESM::Attribute& attribute : store)
|
||||
{
|
||||
const int offset = sColumnOffsets[i / perCol];
|
||||
const int row = static_cast<int>(i % perCol);
|
||||
const int offset = sColumnOffsets[i / mPerCol];
|
||||
const int row = static_cast<int>(i % mPerCol);
|
||||
Widgets widgets;
|
||||
widgets.mMultiplier = mAssignWidget->createWidget<MyGUI::TextBox>(
|
||||
"SandTextVCenter", { offset, 20 * row, 100, 20 }, MyGUI::Align::Default);
|
||||
|
|
@ -72,12 +72,13 @@ namespace MWGui
|
|||
widgets.mButton->setCaption(attribute.mName);
|
||||
widgets.mValue = hbox->createWidget<Gui::AutoSizedTextBox>("SandText", {}, MyGUI::Align::Default);
|
||||
mAttributeWidgets.emplace(attribute.mId, widgets);
|
||||
mAttributeButtons.emplace_back(widgets.mButton);
|
||||
++i;
|
||||
}
|
||||
|
||||
mAssignWidget->setVisibleVScroll(false);
|
||||
mAssignWidget->setCanvasSize(MyGUI::IntSize(
|
||||
mAssignWidget->getWidth(), std::max(mAssignWidget->getHeight(), static_cast<int>(20 * perCol))));
|
||||
mAssignWidget->getWidth(), std::max(mAssignWidget->getHeight(), static_cast<int>(20 * mPerCol))));
|
||||
mAssignWidget->setVisibleVScroll(true);
|
||||
mAssignWidget->setViewOffset(MyGUI::IntPoint());
|
||||
}
|
||||
|
|
@ -90,6 +91,15 @@ namespace MWGui
|
|||
mCoins.push_back(image);
|
||||
}
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mDisableGamepadCursor = true;
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mX = "#{sDone}";
|
||||
mOkButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sDone", {})));
|
||||
}
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
|
|
@ -217,6 +227,13 @@ namespace MWGui
|
|||
|
||||
center();
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerFocus = 0;
|
||||
for (size_t i = 0; i < mAttributeButtons.size(); i++)
|
||||
setControllerFocus(mAttributeButtons, i, i == 0);
|
||||
}
|
||||
|
||||
// Play LevelUp Music
|
||||
MWBase::Environment::get().getSoundManager()->streamMusic(MWSound::triumphMusic, MWSound::MusicType::Normal);
|
||||
}
|
||||
|
|
@ -363,4 +380,44 @@ namespace MWGui
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool LevelupDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mControllerFocus < mAttributeButtons.size())
|
||||
onAttributeClicked(mAttributeButtons[mControllerFocus]);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Item Gold Up"));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
{
|
||||
onOkButtonClicked(mOkButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
setControllerFocus(mAttributeButtons, mControllerFocus, false);
|
||||
if (mControllerFocus % mPerCol == 0)
|
||||
mControllerFocus += mPerCol - 1;
|
||||
else
|
||||
mControllerFocus--;
|
||||
setControllerFocus(mAttributeButtons, mControllerFocus, true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
setControllerFocus(mAttributeButtons, mControllerFocus, false);
|
||||
if (mControllerFocus % mPerCol == mPerCol - 1)
|
||||
mControllerFocus -= mPerCol - 1;
|
||||
else
|
||||
mControllerFocus++;
|
||||
setControllerFocus(mAttributeButtons, mControllerFocus, true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT || arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
|
||||
{
|
||||
setControllerFocus(mAttributeButtons, mControllerFocus, false);
|
||||
mControllerFocus = (mControllerFocus + mPerCol) % mAttributeButtons.size();
|
||||
setControllerFocus(mAttributeButtons, mControllerFocus, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ namespace MWGui
|
|||
|
||||
std::vector<ESM::Attribute::AttributeID> mSpentAttributes;
|
||||
|
||||
size_t mPerCol;
|
||||
unsigned int mCoinCount;
|
||||
|
||||
void onOkButtonClicked(MyGUI::Widget* sender);
|
||||
|
|
@ -49,6 +50,10 @@ namespace MWGui
|
|||
|
||||
std::string_view getLevelupClassImage(
|
||||
const int combatIncreases, const int magicIncreases, const int stealthIncreases);
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
std::vector<MyGUI::Button*> mAttributeButtons;
|
||||
size_t mControllerFocus;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "mainmenu.hpp"
|
||||
|
||||
#include <MyGUI_Gui.h>
|
||||
#include <MyGUI_InputManager.h>
|
||||
#include <MyGUI_RenderManager.h>
|
||||
#include <MyGUI_TextBox.h>
|
||||
|
||||
|
|
@ -105,6 +106,7 @@ namespace MWGui
|
|||
constexpr VFS::Path::NormalizedView menuBackgroundVideo("video/menu_background.bik");
|
||||
|
||||
mHasAnimatedMenu = mVFS->exists(menuBackgroundVideo);
|
||||
mDisableGamepadCursor = Settings::gui().mControllerMenus;
|
||||
|
||||
updateMenu();
|
||||
}
|
||||
|
|
@ -163,9 +165,7 @@ namespace MWGui
|
|||
const std::string& name = *sender->getUserData<std::string>();
|
||||
winMgr->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
if (name == "return")
|
||||
{
|
||||
winMgr->removeGuiMode(GM_MainMenu);
|
||||
}
|
||||
else if (name == "credits")
|
||||
winMgr->playVideo("mw_credits.bik", true);
|
||||
else if (name == "exitgame")
|
||||
|
|
@ -208,6 +208,32 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
bool MainMenu::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Space, 0, false);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B || arg.button == SDL_CONTROLLER_BUTTON_START)
|
||||
{
|
||||
if (mButtons["return"]->getVisible())
|
||||
onButtonClicked(mButtons["return"]);
|
||||
else
|
||||
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Escape, 0, false);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::LeftShift);
|
||||
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Tab, 0, false);
|
||||
MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::LeftShift);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Tab, 0, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainMenu::showBackground(bool show)
|
||||
{
|
||||
if (mVideo && !show)
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ namespace MWGui
|
|||
MainMenu(int w, int h, const VFS::Manager* vfs, const std::string& versionDescription);
|
||||
|
||||
void onResChange(int w, int h) override;
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
|
||||
void setVisible(bool visible) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <MyGUI_RotatingSkin.h>
|
||||
#include <MyGUI_ScrollView.h>
|
||||
#include <MyGUI_TextIterator.h>
|
||||
#include <MyGUI_Window.h>
|
||||
|
||||
#include <components/esm3/esmwriter.hpp>
|
||||
#include <components/esm3/globalmap.hpp>
|
||||
|
|
@ -830,6 +831,14 @@ namespace MWGui
|
|||
|
||||
mGlobalMap->setVisible(global);
|
||||
mLocalMap->setVisible(!global);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerButtons.mB = "#{sBack}";
|
||||
mControllerButtons.mX = global ? "#{sLocal}" : "#{sWorld}";
|
||||
mControllerButtons.mY = "#{sCenter}";
|
||||
mControllerButtons.mDpad = Settings::map().mAllowZooming ? "" : "#{sMove}";
|
||||
}
|
||||
}
|
||||
|
||||
void MapWindow::onNoteEditOk()
|
||||
|
|
@ -1018,7 +1027,20 @@ namespace MWGui
|
|||
void MapWindow::setVisible(bool visible)
|
||||
{
|
||||
WindowBase::setVisible(visible);
|
||||
mButton->setVisible(visible && MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_None);
|
||||
MWGui::GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode();
|
||||
mButton->setVisible(visible && mode != MWGui::GM_None);
|
||||
|
||||
if (Settings::gui().mControllerMenus && mode == MWGui::GM_None && pinned() && visible)
|
||||
{
|
||||
// Restore the window to pinned size.
|
||||
MyGUI::Window* window = mMainWidget->castType<MyGUI::Window>();
|
||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
const float x = Settings::windows().mMapX * viewSize.width;
|
||||
const float y = Settings::windows().mMapY * viewSize.height;
|
||||
const float w = Settings::windows().mMapW * viewSize.width;
|
||||
const float h = Settings::windows().mMapH * viewSize.height;
|
||||
window->setCoord(x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
void MapWindow::renderGlobalMap()
|
||||
|
|
@ -1206,6 +1228,8 @@ namespace MWGui
|
|||
mLocalMap->setVisible(!global);
|
||||
|
||||
mButton->setCaptionWithReplacing(global ? "#{sLocal}" : "#{sWorld}");
|
||||
mControllerButtons.mX = global ? "#{sLocal}" : "#{sWorld}";
|
||||
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
|
||||
}
|
||||
|
||||
void MapWindow::onPinToggled()
|
||||
|
|
@ -1217,7 +1241,9 @@ namespace MWGui
|
|||
|
||||
void MapWindow::onTitleDoubleClicked()
|
||||
{
|
||||
if (MyGUI::InputManager::getInstance().isShiftPressed())
|
||||
if (Settings::gui().mControllerMenus)
|
||||
return;
|
||||
else if (MyGUI::InputManager::getInstance().isShiftPressed())
|
||||
MWBase::Environment::get().getWindowManager()->toggleMaximized(this);
|
||||
else if (!mPinned)
|
||||
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Map);
|
||||
|
|
@ -1367,6 +1393,73 @@ namespace MWGui
|
|||
mGlobalMapRender->asyncWritePng();
|
||||
}
|
||||
|
||||
bool MapWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
{
|
||||
onWorldButtonClicked(mButton);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_Y)
|
||||
{
|
||||
centerView();
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
shiftMap(0, 100);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
shiftMap(0, -100);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
|
||||
shiftMap(100, 0);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
|
||||
shiftMap(-100, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MapWindow::shiftMap(int dx, int dy)
|
||||
{
|
||||
if (dx == 0 && dy == 0)
|
||||
return;
|
||||
|
||||
if (!Settings::map().mGlobal)
|
||||
{
|
||||
mNeedDoorMarkersUpdate = true;
|
||||
mLocalMap->setViewOffset(
|
||||
MyGUI::IntPoint(mLocalMap->getViewOffset().left + dx, mLocalMap->getViewOffset().top + dy));
|
||||
}
|
||||
else
|
||||
{
|
||||
mGlobalMap->setViewOffset(
|
||||
MyGUI::IntPoint(mGlobalMap->getViewOffset().left + dx, mGlobalMap->getViewOffset().top + dy));
|
||||
}
|
||||
}
|
||||
|
||||
void MapWindow::setActiveControllerWindow(bool active)
|
||||
{
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
if (winMgr->getMode() == MWGui::GM_Inventory)
|
||||
{
|
||||
// Fill the screen, or limit to a certain size on large screens. Size chosen to
|
||||
// show the entire local map without scrolling.
|
||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
MyGUI::IntSize canvasSize = mLocalMap->getCanvasSize();
|
||||
MyGUI::IntSize borderSize = mMainWidget->getSize() - mMainWidget->getClientWidget()->getSize();
|
||||
|
||||
int width = std::min(viewSize.width, canvasSize.width + borderSize.width);
|
||||
int height = std::min(winMgr->getControllerMenuHeight(), canvasSize.height + borderSize.height);
|
||||
int x = (viewSize.width - width) / 2;
|
||||
int y = (viewSize.height - height) / 2;
|
||||
|
||||
MyGUI::Window* window = mMainWidget->castType<MyGUI::Window>();
|
||||
window->setCoord(x, active ? y : viewSize.height + 1, width, height);
|
||||
}
|
||||
|
||||
WindowBase::setActiveControllerWindow(active);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
EditNoteDialog::EditNoteDialog()
|
||||
|
|
@ -1380,6 +1473,12 @@ namespace MWGui
|
|||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EditNoteDialog::onCancelButtonClicked);
|
||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EditNoteDialog::onOkButtonClicked);
|
||||
mDeleteButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EditNoteDialog::onDeleteButtonClicked);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerButtons.mA = "#{Interface:OK}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
}
|
||||
}
|
||||
|
||||
void EditNoteDialog::showDeleteButton(bool show)
|
||||
|
|
@ -1407,6 +1506,13 @@ namespace MWGui
|
|||
WindowModal::onOpen();
|
||||
center();
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerFocus = getDeleteButtonShown() ? 1 : 0;
|
||||
mOkButton->setStateSelected(true);
|
||||
mCancelButton->setStateSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
void EditNoteDialog::onCancelButtonClicked(MyGUI::Widget* sender)
|
||||
|
|
@ -1424,6 +1530,78 @@ namespace MWGui
|
|||
eventDeleteClicked();
|
||||
}
|
||||
|
||||
ControllerButtons* EditNoteDialog::getControllerButtons()
|
||||
{
|
||||
mControllerButtons.mX = getDeleteButtonShown() ? "#{sDelete}" : "";
|
||||
return &mControllerButtons;
|
||||
}
|
||||
|
||||
bool EditNoteDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (getDeleteButtonShown())
|
||||
{
|
||||
if (mControllerFocus == 0)
|
||||
onDeleteButtonClicked(mDeleteButton);
|
||||
else if (mControllerFocus == 1)
|
||||
onOkButtonClicked(mOkButton);
|
||||
else
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mControllerFocus == 0)
|
||||
onOkButtonClicked(mOkButton);
|
||||
else
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
{
|
||||
if (getDeleteButtonShown())
|
||||
onDeleteButtonClicked(mDeleteButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
|
||||
{
|
||||
if (getDeleteButtonShown())
|
||||
{
|
||||
mControllerFocus = wrap(mControllerFocus - 1, 3);
|
||||
mDeleteButton->setStateSelected(mControllerFocus == 0);
|
||||
mOkButton->setStateSelected(mControllerFocus == 1);
|
||||
mCancelButton->setStateSelected(mControllerFocus == 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
mControllerFocus = 0;
|
||||
mOkButton->setStateSelected(mControllerFocus == 0);
|
||||
mCancelButton->setStateSelected(mControllerFocus == 1);
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
|
||||
{
|
||||
if (getDeleteButtonShown())
|
||||
{
|
||||
mControllerFocus = wrap(mControllerFocus + 1, 3);
|
||||
mDeleteButton->setStateSelected(mControllerFocus == 0);
|
||||
mOkButton->setStateSelected(mControllerFocus == 1);
|
||||
mCancelButton->setStateSelected(mControllerFocus == 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
mControllerFocus = 1;
|
||||
mOkButton->setStateSelected(mControllerFocus == 0);
|
||||
mCancelButton->setStateSelected(mControllerFocus == 1);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LocalMapBase::MarkerUserData::isPositionExplored() const
|
||||
{
|
||||
if (!mLocalMapRender)
|
||||
|
|
|
|||
|
|
@ -212,6 +212,8 @@ namespace MWGui
|
|||
EventHandle_Void eventDeleteClicked;
|
||||
EventHandle_Void eventOkClicked;
|
||||
|
||||
ControllerButtons* getControllerButtons() override;
|
||||
|
||||
private:
|
||||
void onCancelButtonClicked(MyGUI::Widget* sender);
|
||||
void onOkButtonClicked(MyGUI::Widget* sender);
|
||||
|
|
@ -221,6 +223,9 @@ namespace MWGui
|
|||
MyGUI::Button* mOkButton;
|
||||
MyGUI::Button* mCancelButton;
|
||||
MyGUI::Button* mDeleteButton;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
int mControllerFocus;
|
||||
};
|
||||
|
||||
class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase, public NoDrop
|
||||
|
|
@ -265,6 +270,10 @@ namespace MWGui
|
|||
|
||||
std::string_view getWindowIdForLua() const override { return "Map"; }
|
||||
|
||||
protected:
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
void setActiveControllerWindow(bool active) override;
|
||||
|
||||
private:
|
||||
void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
||||
void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
||||
|
|
@ -283,6 +292,7 @@ namespace MWGui
|
|||
void setGlobalMapMarkerTooltip(MyGUI::Widget* widget, int x, int y);
|
||||
float getMarkerSize(size_t agregatedWeight) const;
|
||||
void resizeGlobalMap();
|
||||
void shiftMap(int dx, int dy);
|
||||
void worldPosToGlobalMapImageSpace(float x, float z, float& imageX, float& imageY) const;
|
||||
MyGUI::IntCoord createMarkerCoords(float x, float y, float agregatedWeight) const;
|
||||
MyGUI::Widget* createMarker(const std::string& name, float x, float y, float agregatedWeight);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,13 @@ namespace MWGui
|
|||
getWidget(mGoldLabel, "PlayerGold");
|
||||
|
||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onOkButtonClick);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mDisableGamepadCursor = true;
|
||||
mControllerButtons.mA = "#{sRepair}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
}
|
||||
}
|
||||
|
||||
void MerchantRepair::setPtr(const MWWorld::Ptr& actor)
|
||||
|
|
@ -38,6 +45,7 @@ namespace MWGui
|
|||
|
||||
while (mList->getChildCount())
|
||||
MyGUI::Gui::getInstance().destroyWidget(mList->getChildAt(0));
|
||||
mButtons.clear();
|
||||
|
||||
const int lineHeight = Settings::gui().mFontSize + 2;
|
||||
int currentY = 0;
|
||||
|
|
@ -101,6 +109,15 @@ namespace MWGui
|
|||
button->eventMouseWheel += MyGUI::newDelegate(this, &MerchantRepair::onMouseWheel);
|
||||
button->setUserString("ToolTipType", "ItemPtr");
|
||||
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onRepairButtonClick);
|
||||
if (price <= playerGold)
|
||||
mButtons.emplace_back(std::make_pair(button, mButtons.size()));
|
||||
}
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerFocus = 0;
|
||||
if (mButtons.size() > 0)
|
||||
mButtons[0].first->setStateSelected(true);
|
||||
}
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the
|
||||
|
|
@ -157,4 +174,49 @@ namespace MWGui
|
|||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_MerchantRepair);
|
||||
}
|
||||
|
||||
bool MerchantRepair::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mControllerFocus < mButtons.size())
|
||||
onRepairButtonClick(mButtons[mControllerFocus].first);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onOkButtonClick(mOkButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
if (mButtons.size() <= 1)
|
||||
return true;
|
||||
|
||||
mButtons[mControllerFocus].first->setStateSelected(false);
|
||||
mControllerFocus = wrap(mControllerFocus - 1, mButtons.size());
|
||||
mButtons[mControllerFocus].first->setStateSelected(true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
if (mButtons.size() <= 1)
|
||||
return true;
|
||||
|
||||
mButtons[mControllerFocus].first->setStateSelected(false);
|
||||
mControllerFocus = wrap(mControllerFocus + 1, mButtons.size());
|
||||
mButtons[mControllerFocus].first->setStateSelected(true);
|
||||
}
|
||||
|
||||
// Scroll the list to keep the active item in view
|
||||
if (mControllerFocus < mButtons.size())
|
||||
{
|
||||
size_t line = mButtons[mControllerFocus].second;
|
||||
if (line <= 5)
|
||||
mList->setViewOffset(MyGUI::IntPoint(0, 0));
|
||||
else
|
||||
{
|
||||
const int lineHeight = Settings::gui().mFontSize + 2;
|
||||
mList->setViewOffset(MyGUI::IntPoint(0, -lineHeight * (line - 5)));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,13 +22,18 @@ namespace MWGui
|
|||
MyGUI::ScrollView* mList;
|
||||
MyGUI::Button* mOkButton;
|
||||
MyGUI::TextBox* mGoldLabel;
|
||||
/// List of enabled/repairable items and their index in the full list.
|
||||
std::vector<std::pair<MyGUI::Button*, size_t>> mButtons;
|
||||
|
||||
MWWorld::Ptr mActor;
|
||||
|
||||
size_t mControllerFocus;
|
||||
|
||||
protected:
|
||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||
void onRepairButtonClick(MyGUI::Widget* sender);
|
||||
void onOkButtonClick(MyGUI::Widget* sender);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/misc/strings/algorithm.hpp>
|
||||
#include <components/settings/values.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
|
|
@ -217,7 +218,7 @@ namespace MWGui
|
|||
}
|
||||
|
||||
InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message,
|
||||
const std::vector<std::string>& buttons, bool immediate, int defaultFocus)
|
||||
const std::vector<std::string>& buttons, bool immediate, size_t defaultFocus)
|
||||
: WindowModal(MWBase::Environment::get().getWindowManager()->isGuiMode()
|
||||
? "openmw_interactive_messagebox_notransp.layout"
|
||||
: "openmw_interactive_messagebox.layout")
|
||||
|
|
@ -225,6 +226,7 @@ namespace MWGui
|
|||
, mButtonPressed(-1)
|
||||
, mDefaultFocus(defaultFocus)
|
||||
, mImmediate(immediate)
|
||||
, mControllerFocus(0)
|
||||
{
|
||||
int textPadding = 10; // padding between text-widget and main-widget
|
||||
int textButtonPadding = 10; // padding between the text-widget und the button-widget
|
||||
|
|
@ -280,6 +282,22 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mDisableGamepadCursor = true;
|
||||
mControllerButtons.mA = "#{Interface:OK}";
|
||||
|
||||
// If we have more than one button, we need to set the focus to the first one.
|
||||
if (mButtons.size() > 1)
|
||||
{
|
||||
mControllerFocus = 0;
|
||||
if (mDefaultFocus < mButtons.size())
|
||||
mControllerFocus = mDefaultFocus;
|
||||
for (size_t i = 0; i < mButtons.size(); ++i)
|
||||
mButtons[i]->setStateSelected(i == mControllerFocus);
|
||||
}
|
||||
}
|
||||
|
||||
MyGUI::IntSize mainWidgetSize;
|
||||
if (buttonsWidth < textSize.width)
|
||||
{
|
||||
|
|
@ -380,7 +398,7 @@ namespace MWGui
|
|||
|
||||
MyGUI::Widget* InteractiveMessageBox::getDefaultKeyFocus()
|
||||
{
|
||||
if (mDefaultFocus >= 0 && mDefaultFocus < static_cast<int>(mButtons.size()))
|
||||
if (mDefaultFocus < mButtons.size())
|
||||
return mButtons[mDefaultFocus];
|
||||
auto& languageManager = MyGUI::LanguageManager::getInstance();
|
||||
std::vector<MyGUI::UString> keywords{ languageManager.replaceTags("#{sOk}"),
|
||||
|
|
@ -431,4 +449,45 @@ namespace MWGui
|
|||
return mButtonPressed;
|
||||
}
|
||||
|
||||
bool InteractiveMessageBox::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (!mButtons.empty())
|
||||
{
|
||||
if (mControllerFocus >= mButtons.size())
|
||||
mControllerFocus = mButtons.size() - 1;
|
||||
buttonActivated(mButtons[mControllerFocus]);
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
if (mButtons.size() == 1)
|
||||
buttonActivated(mButtons[0]);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP || arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
|
||||
{
|
||||
if (mButtons.size() <= 1)
|
||||
return true;
|
||||
if (mButtons.size() == 2 && mControllerFocus == 0)
|
||||
return true;
|
||||
|
||||
setControllerFocus(mButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus - 1, mButtons.size());
|
||||
setControllerFocus(mButtons, mControllerFocus, true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN || arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
|
||||
{
|
||||
if (mButtons.size() <= 1)
|
||||
return true;
|
||||
if (mButtons.size() == 2 && mControllerFocus == 1)
|
||||
return true;
|
||||
|
||||
setControllerFocus(mButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus + 1, mButtons.size());
|
||||
setControllerFocus(mButtons, mControllerFocus, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ namespace MWGui
|
|||
{
|
||||
public:
|
||||
InteractiveMessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message,
|
||||
const std::vector<std::string>& buttons, bool immediate, int defaultFocus);
|
||||
const std::vector<std::string>& buttons, bool immediate, size_t defaultFocus);
|
||||
void mousePressed(MyGUI::Widget* _widget);
|
||||
int readPressedButton();
|
||||
|
||||
|
|
@ -103,6 +103,8 @@ namespace MWGui
|
|||
|
||||
bool mMarkedToDelete;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
|
||||
private:
|
||||
void buttonActivated(MyGUI::Widget* _widget);
|
||||
|
||||
|
|
@ -112,8 +114,9 @@ namespace MWGui
|
|||
std::vector<MyGUI::Button*> mButtons;
|
||||
|
||||
int mButtonPressed;
|
||||
int mDefaultFocus;
|
||||
size_t mDefaultFocus;
|
||||
bool mImmediate;
|
||||
size_t mControllerFocus;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <components/esm3/quickkeys.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
#include <components/settings/values.hpp>
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
|
@ -39,7 +40,7 @@ namespace MWGui
|
|||
, mKey(std::vector<keyData>(10))
|
||||
, mSelected(nullptr)
|
||||
, mActivated(nullptr)
|
||||
|
||||
, mControllerFocus(0)
|
||||
{
|
||||
getWidget(mOkButton, "OKButton");
|
||||
getWidget(mInstructionLabel, "InstructionLabel");
|
||||
|
|
@ -58,6 +59,12 @@ namespace MWGui
|
|||
|
||||
unassign(&mKey[i]);
|
||||
}
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:OK}";
|
||||
}
|
||||
}
|
||||
|
||||
void QuickKeysMenu::clear()
|
||||
|
|
@ -108,6 +115,13 @@ namespace MWGui
|
|||
{
|
||||
validate(index);
|
||||
}
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerFocus = 0;
|
||||
for (size_t i = 0; i < mKey.size(); i++)
|
||||
mKey[i].button->setControllerFocus(i == mControllerFocus);
|
||||
}
|
||||
}
|
||||
|
||||
void QuickKeysMenu::onClose()
|
||||
|
|
@ -454,11 +468,45 @@ namespace MWGui
|
|||
MWBase::Environment::get().getWindowManager()->updateSpellWindow();
|
||||
}
|
||||
|
||||
bool QuickKeysMenu::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
onQuickKeyButtonClicked(mKey[mControllerFocus].button);
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
onOkButtonClicked(mOkButton);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP || arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
mControllerFocus = (mControllerFocus + 5) % 10;
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
|
||||
{
|
||||
if (mControllerFocus == 0)
|
||||
mControllerFocus = 4;
|
||||
else if (mControllerFocus == 5)
|
||||
mControllerFocus = 9;
|
||||
else
|
||||
mControllerFocus--;
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
|
||||
{
|
||||
if (mControllerFocus == 4)
|
||||
mControllerFocus = 0;
|
||||
else if (mControllerFocus == 9)
|
||||
mControllerFocus = 5;
|
||||
else
|
||||
mControllerFocus++;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mKey.size(); i++)
|
||||
mKey[i].button->setControllerFocus(i == mControllerFocus);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------
|
||||
|
||||
QuickKeysMenuAssign::QuickKeysMenuAssign(QuickKeysMenu* parent)
|
||||
: WindowModal("openmw_quickkeys_menu_assign.layout")
|
||||
, mParent(parent)
|
||||
, mControllerFocus(0)
|
||||
{
|
||||
getWidget(mLabel, "Label");
|
||||
getWidget(mItemButton, "ItemButton");
|
||||
|
|
@ -489,9 +537,45 @@ namespace MWGui
|
|||
mCancelButton->setCoord((maxWidth - mCancelButton->getTextSize().width - 24) / 2 + 8, mCancelButton->getTop(),
|
||||
mCancelButton->getTextSize().width + 24, mCancelButton->getHeight());
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mDisableGamepadCursor = true;
|
||||
mItemButton->setStateSelected(true);
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
}
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
bool QuickKeysMenuAssign::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mControllerFocus == 0)
|
||||
mParent->onItemButtonClicked(mItemButton);
|
||||
else if (mControllerFocus == 1)
|
||||
mParent->onMagicButtonClicked(mMagicButton);
|
||||
else if (mControllerFocus == 2)
|
||||
mParent->onUnassignButtonClicked(mUnassignButton);
|
||||
else if (mControllerFocus == 3)
|
||||
mParent->onCancelButtonClicked(mCancelButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
mParent->onCancelButtonClicked(mCancelButton);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
mControllerFocus = wrap(mControllerFocus - 1, 4);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
mControllerFocus = wrap(mControllerFocus + 1, 4);
|
||||
|
||||
mItemButton->setStateSelected(mControllerFocus == 0);
|
||||
mMagicButton->setStateSelected(mControllerFocus == 1);
|
||||
mUnassignButton->setStateSelected(mControllerFocus == 2);
|
||||
mCancelButton->setStateSelected(mControllerFocus == 3);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QuickKeysMenu::write(ESM::ESMWriter& writer)
|
||||
{
|
||||
writer.startRecord(ESM::REC_KEYS);
|
||||
|
|
@ -601,6 +685,12 @@ namespace MWGui
|
|||
mMagicList->setHighlightSelected(false);
|
||||
mMagicList->eventSpellClicked += MyGUI::newDelegate(this, &MagicSelectionDialog::onModelIndexSelected);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
}
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
|
|
@ -632,4 +722,13 @@ namespace MWGui
|
|||
mParent->onAssignMagic(spell.mId);
|
||||
}
|
||||
|
||||
bool MagicSelectionDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
else
|
||||
mMagicList->onControllerButton(arg.button);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ namespace MWGui
|
|||
inline void validate(int index);
|
||||
void unassign(keyData* key);
|
||||
void assignItem(MWWorld::Ptr item);
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
size_t mControllerFocus;
|
||||
};
|
||||
|
||||
class QuickKeysMenuAssign : public WindowModal
|
||||
|
|
@ -88,6 +91,9 @@ namespace MWGui
|
|||
MyGUI::Button* mCancelButton;
|
||||
|
||||
QuickKeysMenu* mParent;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
int mControllerFocus;
|
||||
};
|
||||
|
||||
class MagicSelectionDialog : public WindowModal
|
||||
|
|
@ -106,6 +112,9 @@ namespace MWGui
|
|||
|
||||
void onCancelButtonClicked(MyGUI::Widget* sender);
|
||||
void onModelIndexSelected(SpellModel::ModelIndex index);
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
int mControllerFocus;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,16 +23,6 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
int wrap(int index, int max)
|
||||
{
|
||||
if (index < 0)
|
||||
return max - 1;
|
||||
else if (index >= max)
|
||||
return 0;
|
||||
else
|
||||
return index;
|
||||
}
|
||||
|
||||
bool sortRaces(const std::pair<ESM::RefId, std::string>& left, const std::pair<ESM::RefId, std::string>& right)
|
||||
{
|
||||
return left.second.compare(right.second) < 0;
|
||||
|
|
@ -108,15 +98,23 @@ namespace MWGui
|
|||
MWBase::Environment::get().getWindowManager()->getGameSettingString("sRaceMenu7", "Specials"));
|
||||
getWidget(mSpellPowerList, "SpellPowerList");
|
||||
|
||||
MyGUI::Button* backButton;
|
||||
getWidget(backButton, "BackButton");
|
||||
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onBackClicked);
|
||||
getWidget(mBackButton, "BackButton");
|
||||
mBackButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onBackClicked);
|
||||
|
||||
MyGUI::Button* okButton;
|
||||
getWidget(okButton, "OKButton");
|
||||
okButton->setCaption(
|
||||
getWidget(mOkButton, "OKButton");
|
||||
mOkButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {})));
|
||||
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onOkClicked);
|
||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onOkClicked);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerButtons.mLStick = "#{sMouse}";
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{sBack}";
|
||||
mControllerButtons.mY = "#{sSex}";
|
||||
mControllerButtons.mL1 = "#{sHair}";
|
||||
mControllerButtons.mR1 = "#{sFace}";
|
||||
}
|
||||
|
||||
updateRaces();
|
||||
updateSkills();
|
||||
|
|
@ -129,8 +127,17 @@ namespace MWGui
|
|||
getWidget(okButton, "OKButton");
|
||||
|
||||
if (shown)
|
||||
{
|
||||
okButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", {})));
|
||||
mControllerButtons.mX = "#{sNext}";
|
||||
}
|
||||
else if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
okButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sDone", {})));
|
||||
mControllerButtons.mX = "#{sDone}";
|
||||
}
|
||||
else
|
||||
okButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {})));
|
||||
|
|
@ -462,6 +469,55 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
bool RaceDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onBackClicked(mBackButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
{
|
||||
onOkClicked(mOkButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_Y)
|
||||
{
|
||||
onSelectNextGender(nullptr);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
|
||||
{
|
||||
onSelectNextHair(nullptr);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
|
||||
{
|
||||
onSelectNextFace(nullptr);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
winMgr->setKeyFocusWidget(mRaceList);
|
||||
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowUp, 0, false);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
winMgr->setKeyFocusWidget(mRaceList);
|
||||
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowDown, 0, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RaceDialog::onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg)
|
||||
{
|
||||
if (arg.axis == SDL_CONTROLLER_AXIS_RIGHTX)
|
||||
{
|
||||
onPreviewScroll(nullptr, arg.value < 0 ? 1 : -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const ESM::NPC& RaceDialog::getResult() const
|
||||
{
|
||||
return mPreview->getPrototype();
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ namespace MWGui
|
|||
MyGUI::ImageBox* mPreviewImage;
|
||||
MyGUI::ListBox* mRaceList;
|
||||
MyGUI::ScrollBar* mHeadRotate;
|
||||
MyGUI::Button* mBackButton;
|
||||
MyGUI::Button* mOkButton;
|
||||
|
||||
MyGUI::Widget* mSkillList;
|
||||
std::vector<MyGUI::Widget*> mSkillItems;
|
||||
|
|
@ -118,6 +120,9 @@ namespace MWGui
|
|||
std::unique_ptr<MyGUI::ITexture> mPreviewTexture;
|
||||
|
||||
bool mPreviewDirty;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
bool onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg) override;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@ namespace MWGui
|
|||
mBox->setDisplayMode(ItemChargeView::DisplayMode_EnchantmentCharge);
|
||||
|
||||
mGemIcon->eventMouseButtonClick += MyGUI::newDelegate(this, &Recharge::onSelectItem);
|
||||
|
||||
mControllerButtons.mA = "#{OMWEngine:RechargeSelect}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
mControllerButtons.mY = "#{sSoulGem}";
|
||||
}
|
||||
|
||||
void Recharge::onOpen()
|
||||
|
|
@ -136,4 +140,18 @@ namespace MWGui
|
|||
updateView();
|
||||
}
|
||||
|
||||
bool Recharge::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if ((arg.button == SDL_CONTROLLER_BUTTON_A && !mGemBox->getVisible()) || arg.button == SDL_CONTROLLER_BUTTON_Y)
|
||||
{
|
||||
onSelectItem(mGemIcon);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
onCancel(mCancelButton);
|
||||
else
|
||||
mBox->onControllerButton(arg.button);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ namespace MWGui
|
|||
void onItemClicked(MyGUI::Widget* sender, const MWWorld::Ptr& item);
|
||||
void onCancel(MyGUI::Widget* sender);
|
||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@ namespace MWGui
|
|||
mRepairBox->setDisplayMode(ItemChargeView::DisplayMode_Health);
|
||||
|
||||
mToolIcon->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onSelectItem);
|
||||
|
||||
mControllerButtons.mA = "#{sRepair}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
mControllerButtons.mY = "#{OMWEngine:RepairTool}";
|
||||
}
|
||||
|
||||
void Repair::onOpen()
|
||||
|
|
@ -150,4 +154,18 @@ namespace MWGui
|
|||
updateRepairView();
|
||||
}
|
||||
|
||||
bool Repair::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if ((arg.button == SDL_CONTROLLER_BUTTON_A && !mToolBox->getVisible()) || arg.button == SDL_CONTROLLER_BUTTON_Y)
|
||||
{
|
||||
onSelectItem(mToolIcon);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
onCancel(mCancelButton);
|
||||
else
|
||||
mRepairBox->onControllerButton(arg.button);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ namespace MWGui
|
|||
|
||||
void onRepairItem(MyGUI::Widget* sender, const MWWorld::Ptr& ptr);
|
||||
void onCancel(MyGUI::Widget* sender);
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ namespace MWGui
|
|||
ReviewDialog::ReviewDialog()
|
||||
: WindowModal("openmw_chargen_review.layout")
|
||||
, mUpdateSkillArea(false)
|
||||
, mControllerFocus(5)
|
||||
{
|
||||
// Centre dialog
|
||||
center();
|
||||
|
|
@ -46,21 +47,25 @@ namespace MWGui
|
|||
getWidget(button, "NameButton");
|
||||
adjustButtonSize(button);
|
||||
button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onNameClicked);
|
||||
mButtons.push_back(button);
|
||||
|
||||
getWidget(mRaceWidget, "RaceText");
|
||||
getWidget(button, "RaceButton");
|
||||
adjustButtonSize(button);
|
||||
button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onRaceClicked);
|
||||
mButtons.push_back(button);
|
||||
|
||||
getWidget(mClassWidget, "ClassText");
|
||||
getWidget(button, "ClassButton");
|
||||
adjustButtonSize(button);
|
||||
button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onClassClicked);
|
||||
mButtons.push_back(button);
|
||||
|
||||
getWidget(mBirthSignWidget, "SignText");
|
||||
getWidget(button, "SignButton");
|
||||
adjustButtonSize(button);
|
||||
button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onBirthSignClicked);
|
||||
mButtons.push_back(button);
|
||||
|
||||
// Setup dynamic stats
|
||||
getWidget(mHealth, "Health");
|
||||
|
|
@ -108,10 +113,22 @@ namespace MWGui
|
|||
MyGUI::Button* backButton;
|
||||
getWidget(backButton, "BackButton");
|
||||
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onBackClicked);
|
||||
mButtons.push_back(backButton);
|
||||
|
||||
MyGUI::Button* okButton;
|
||||
getWidget(okButton, "OKButton");
|
||||
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onOkClicked);
|
||||
mButtons.push_back(okButton);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
setControllerFocus(mButtons, mControllerFocus, true);
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{sBack}";
|
||||
mControllerButtons.mX = "#{sDone}";
|
||||
okButton->setCaption(
|
||||
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sDone", {})));
|
||||
}
|
||||
}
|
||||
|
||||
void ReviewDialog::onOpen()
|
||||
|
|
@ -522,4 +539,54 @@ namespace MWGui
|
|||
MyGUI::IntPoint(0, static_cast<int>(mSkillView->getViewOffset().top + _rel * 0.3)));
|
||||
}
|
||||
|
||||
bool ReviewDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
switch (mControllerFocus)
|
||||
{
|
||||
case 0:
|
||||
onNameClicked(mButtons[0]);
|
||||
break;
|
||||
case 1:
|
||||
onRaceClicked(mButtons[1]);
|
||||
break;
|
||||
case 2:
|
||||
onClassClicked(mButtons[2]);
|
||||
break;
|
||||
case 3:
|
||||
onBirthSignClicked(mButtons[3]);
|
||||
break;
|
||||
case 4:
|
||||
onBackClicked(mButtons[4]);
|
||||
break;
|
||||
case 5:
|
||||
onOkClicked(mButtons[5]);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onBackClicked(mButtons[4]);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
{
|
||||
onOkClicked(mButtons[5]);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP || arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
|
||||
{
|
||||
setControllerFocus(mButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus - 1, mButtons.size());
|
||||
setControllerFocus(mButtons, mControllerFocus, true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN || arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
|
||||
{
|
||||
setControllerFocus(mButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus + 1, mButtons.size());
|
||||
setControllerFocus(mButtons, mControllerFocus, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ namespace MWGui
|
|||
void onBirthSignClicked(MyGUI::Widget* _sender);
|
||||
|
||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
|
||||
private:
|
||||
void addSkills(const std::vector<ESM::RefId>& skills, const std::string& titleId,
|
||||
|
|
@ -100,6 +101,10 @@ namespace MWGui
|
|||
std::vector<MyGUI::Widget*> mSkillWidgets; //< Skills and other information
|
||||
|
||||
bool mUpdateSkillArea;
|
||||
|
||||
// 0 = Name, 1 = Race, 2 = Class, 3 = BirthSign, 4 = Back, 5 = OK
|
||||
std::vector<MyGUI::Button*> mButtons;
|
||||
int mControllerFocus;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <components/files/conversion.hpp>
|
||||
#include <components/files/memorystream.hpp>
|
||||
#include <components/l10n/manager.hpp>
|
||||
#include <components/misc/strings/format.hpp>
|
||||
#include <components/misc/strings/lower.hpp>
|
||||
#include <components/misc/timeconvert.hpp>
|
||||
#include <components/myguiplatform/myguitexture.hpp>
|
||||
|
|
@ -28,6 +29,7 @@
|
|||
#include "../mwbase/world.hpp"
|
||||
#include "../mwworld/datetimemanager.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/timestamp.hpp"
|
||||
|
||||
#include "../mwstate/character.hpp"
|
||||
|
||||
|
|
@ -64,6 +66,9 @@ namespace MWGui
|
|||
|
||||
// To avoid accidental deletions
|
||||
mDeleteButton->setNeedKeyFocus(false);
|
||||
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
}
|
||||
|
||||
void SaveGameDialog::onSlotActivated(MyGUI::ListBox* sender, size_t pos)
|
||||
|
|
@ -145,6 +150,28 @@ namespace MWGui
|
|||
WindowModal::onOpen();
|
||||
|
||||
mSaveNameEdit->setCaption({});
|
||||
if (Settings::gui().mControllerMenus && mSaving)
|
||||
{
|
||||
// For controller mode, set a default save file name. The format is
|
||||
// "Day 24 - Last Steed 7 p.m."
|
||||
const MWWorld::DateTimeManager& timeManager = *MWBase::Environment::get().getWorld()->getTimeManager();
|
||||
std::string_view month = timeManager.getMonthName();
|
||||
int hour = static_cast<int>(timeManager.getTimeStamp().getHour());
|
||||
bool pm = hour >= 12;
|
||||
if (hour >= 13)
|
||||
hour -= 12;
|
||||
if (hour == 0)
|
||||
hour = 12;
|
||||
|
||||
ESM::EpochTimeStamp currentDate = timeManager.getEpochTimeStamp();
|
||||
std::string daysPassed
|
||||
= Misc::StringUtils::format("#{Calendar:day} %i", timeManager.getTimeStamp().getDay());
|
||||
std::string_view formattedHour(pm ? "#{Calendar:pm}" : "#{Calendar:am}");
|
||||
std::string autoFilename = Misc::StringUtils::format(
|
||||
"%s - %i %s %i %s", daysPassed, currentDate.mDay, month, hour, formattedHour);
|
||||
|
||||
mSaveNameEdit->setCaptionWithReplacing(autoFilename);
|
||||
}
|
||||
if (mSaving)
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveNameEdit);
|
||||
else
|
||||
|
|
@ -159,6 +186,13 @@ namespace MWGui
|
|||
mSaveList->removeAllItems();
|
||||
onSlotSelected(mSaveList, MyGUI::ITEM_NONE);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mOkButtonFocus = true;
|
||||
mOkButton->setStateSelected(true);
|
||||
mCancelButton->setStateSelected(false);
|
||||
}
|
||||
|
||||
MWBase::StateManager* mgr = MWBase::Environment::get().getStateManager();
|
||||
if (mgr->characterBegin() == mgr->characterEnd())
|
||||
return;
|
||||
|
|
@ -491,4 +525,55 @@ namespace MWGui
|
|||
mScreenshotTexture = std::make_unique<MyGUIPlatform::OSGTexture>(texture);
|
||||
mScreenshot->setRenderItemTexture(mScreenshotTexture.get());
|
||||
}
|
||||
|
||||
ControllerButtons* SaveGameDialog::getControllerButtons()
|
||||
{
|
||||
mControllerButtons.mY = mSaving ? "" : "#{OMWEngine:LoadingSelectCharacter}";
|
||||
return &mControllerButtons;
|
||||
}
|
||||
|
||||
bool SaveGameDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mOkButtonFocus)
|
||||
onOkButtonClicked(mOkButton);
|
||||
else
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_Y)
|
||||
{
|
||||
size_t index = mCharacterSelection->getIndexSelected();
|
||||
index = wrap(index + 1, mCharacterSelection->getItemCount());
|
||||
mCharacterSelection->setIndexSelected(index);
|
||||
onCharacterSelected(mCharacterSelection, index);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
winMgr->setKeyFocusWidget(mSaveList);
|
||||
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowUp, 0, false);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
winMgr->setKeyFocusWidget(mSaveList);
|
||||
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowDown, 0, false);
|
||||
}
|
||||
else if ((arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT && !mOkButtonFocus)
|
||||
|| (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT && mOkButtonFocus))
|
||||
{
|
||||
mOkButtonFocus = !mOkButtonFocus;
|
||||
mOkButton->setStateSelected(mOkButtonFocus);
|
||||
mCancelButton->setStateSelected(!mOkButtonFocus);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ namespace MWGui
|
|||
|
||||
void setLoadOrSave(bool load);
|
||||
|
||||
ControllerButtons* getControllerButtons() override;
|
||||
|
||||
private:
|
||||
void confirmDeleteSave();
|
||||
|
||||
|
|
@ -67,6 +69,9 @@ namespace MWGui
|
|||
|
||||
const MWState::Character* mCurrentCharacter;
|
||||
const MWState::Slot* mCurrentSlot;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
bool mOkButtonFocus = true;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <components/widgets/imagebutton.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include "../mwmechanics/actorutil.hpp"
|
||||
|
|
@ -38,6 +39,10 @@ namespace MWGui
|
|||
mCloseButton->eventKeyButtonPressed += MyGUI::newDelegate(this, &ScrollWindow::onKeyButtonPressed);
|
||||
mTakeButton->eventKeyButtonPressed += MyGUI::newDelegate(this, &ScrollWindow::onKeyButtonPressed);
|
||||
|
||||
mControllerScrollWidget = mTextView;
|
||||
mControllerButtons.mB = "#{Interface:Close}";
|
||||
mControllerButtons.mDpad = "#{sScrolldown}";
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
|
|
@ -115,4 +120,32 @@ namespace MWGui
|
|||
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Scroll);
|
||||
}
|
||||
|
||||
void ScrollWindow::onClose()
|
||||
{
|
||||
if (Settings::gui().mControllerMenus)
|
||||
MWBase::Environment::get().getInputManager()->setGamepadGuiCursorEnabled(true);
|
||||
BookWindowBase::onClose();
|
||||
}
|
||||
|
||||
ControllerButtons* ScrollWindow::getControllerButtons()
|
||||
{
|
||||
mControllerButtons.mA = mTakeButton->getVisible() ? "#{sTake}" : "";
|
||||
return &mControllerButtons;
|
||||
}
|
||||
|
||||
bool ScrollWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mTakeButton->getVisible())
|
||||
onTakeButtonClicked(mTakeButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
onCloseButtonClicked(mCloseButton);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP || arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
return false; // Fall through to keyboard
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,15 +20,19 @@ namespace MWGui
|
|||
void setPtr(const MWWorld::Ptr& scroll) override;
|
||||
void setInventoryAllowed(bool allowed);
|
||||
|
||||
void onClose() override;
|
||||
void onResChange(int, int) override { center(); }
|
||||
|
||||
std::string_view getWindowIdForLua() const override { return "Scroll"; }
|
||||
|
||||
ControllerButtons* getControllerButtons() override;
|
||||
|
||||
protected:
|
||||
void onCloseButtonClicked(MyGUI::Widget* _sender);
|
||||
void onTakeButtonClicked(MyGUI::Widget* _sender);
|
||||
void setTakeButtonShow(bool show);
|
||||
void onKeyButtonPressed(MyGUI::Widget* sender, MyGUI::KeyCode key, MyGUI::Char character);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
|
||||
private:
|
||||
Gui::ImageButton* mCloseButton;
|
||||
|
|
|
|||
|
|
@ -462,6 +462,10 @@ namespace MWGui
|
|||
|
||||
i++;
|
||||
}
|
||||
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:OK}";
|
||||
mControllerButtons.mLStick = "#{sMouse}";
|
||||
}
|
||||
|
||||
void SettingsWindow::onTabChanged(MyGUI::TabControl* /*_sender*/, size_t /*index*/)
|
||||
|
|
@ -471,7 +475,7 @@ namespace MWGui
|
|||
|
||||
void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
setVisible(false);
|
||||
MWBase::Environment::get().getWindowManager()->toggleSettingsWindow();
|
||||
}
|
||||
|
||||
void SettingsWindow::onResolutionSelected(MyGUI::ListBox* _sender, size_t index)
|
||||
|
|
@ -1139,4 +1143,32 @@ namespace MWGui
|
|||
mResolutionList->setScrollPosition(0);
|
||||
mControlsBox->setViewOffset(MyGUI::IntPoint(0, 0));
|
||||
}
|
||||
|
||||
bool SettingsWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onOkButtonClicked(mOkButton);
|
||||
return true;
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
|
||||
{
|
||||
size_t index = mSettingsTab->getIndexSelected();
|
||||
index = wrap(index - 1, mSettingsTab->getItemCount());
|
||||
mSettingsTab->setIndexSelected(index);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
return true;
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
|
||||
{
|
||||
size_t index = mSettingsTab->getIndexSelected();
|
||||
index = wrap(index + 1, mSettingsTab->getItemCount());
|
||||
mSettingsTab->setIndexSelected(index);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ namespace MWGui
|
|||
|
||||
void onResChange(int, int) override;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
|
||||
protected:
|
||||
MyGUI::TabControl* mSettingsTab;
|
||||
MyGUI::Button* mOkButton;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <components/settings/values.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
|
|
@ -26,12 +27,21 @@ namespace MWGui
|
|||
SpellBuyingWindow::SpellBuyingWindow()
|
||||
: WindowBase("openmw_spell_buying_window.layout")
|
||||
, mCurrentY(0)
|
||||
, mControllerFocus(0)
|
||||
{
|
||||
getWidget(mCancelButton, "CancelButton");
|
||||
getWidget(mPlayerGold, "PlayerGold");
|
||||
getWidget(mSpellsView, "SpellsView");
|
||||
|
||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellBuyingWindow::onCancelButtonClicked);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mDisableGamepadCursor = true;
|
||||
mControllerButtons.mA = "#{sBuy}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
mControllerButtons.mR3 = "#{sInfo}";
|
||||
}
|
||||
}
|
||||
|
||||
bool SpellBuyingWindow::sortSpells(const ESM::Spell* left, const ESM::Spell* right)
|
||||
|
|
@ -71,6 +81,8 @@ namespace MWGui
|
|||
toAdd->setUserString("SpellCost", std::to_string(spell.mData.mCost));
|
||||
toAdd->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellBuyingWindow::onSpellButtonClick);
|
||||
mSpellsWidgetMap.insert(std::make_pair(toAdd, spell.mId));
|
||||
if (price <= playerGold)
|
||||
mSpellButtons.emplace_back(std::make_pair(toAdd, mSpellsWidgetMap.size()));
|
||||
}
|
||||
|
||||
void SpellBuyingWindow::clearSpells()
|
||||
|
|
@ -80,6 +92,7 @@ namespace MWGui
|
|||
while (mSpellsView->getChildCount())
|
||||
MyGUI::Gui::getInstance().destroyWidget(mSpellsView->getChildAt(0));
|
||||
mSpellsWidgetMap.clear();
|
||||
mSpellButtons.clear();
|
||||
}
|
||||
|
||||
void SpellBuyingWindow::setPtr(const MWWorld::Ptr& actor)
|
||||
|
|
@ -130,6 +143,20 @@ namespace MWGui
|
|||
|
||||
updateLabels();
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerFocus = 0;
|
||||
if (mSpellButtons.size() > 0)
|
||||
{
|
||||
mSpellButtons[0].first->setStateSelected(true);
|
||||
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
winMgr->setControllerTooltip(Settings::gui().mControllerTooltips);
|
||||
if (winMgr->getControllerTooltip())
|
||||
MWBase::Environment::get().getInputManager()->warpMouseToWidget(mSpellButtons[0].first);
|
||||
}
|
||||
}
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the
|
||||
// scrollbar is hidden
|
||||
mSpellsView->setVisibleVScroll(false);
|
||||
|
|
@ -200,4 +227,62 @@ namespace MWGui
|
|||
mSpellsView->setViewOffset(
|
||||
MyGUI::IntPoint(0, static_cast<int>(mSpellsView->getViewOffset().top + _rel * 0.3f)));
|
||||
}
|
||||
|
||||
bool SpellBuyingWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mControllerFocus < mSpellButtons.size())
|
||||
onSpellButtonClick(mSpellButtons[mControllerFocus].first);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSTICK)
|
||||
{
|
||||
// Toggle info tooltip
|
||||
MWBase::Environment::get().getWindowManager()->setControllerTooltip(
|
||||
!MWBase::Environment::get().getWindowManager()->getControllerTooltip());
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
if (mSpellButtons.size() <= 1)
|
||||
return true;
|
||||
|
||||
mSpellButtons[mControllerFocus].first->setStateSelected(false);
|
||||
mControllerFocus = wrap(mControllerFocus - 1, mSpellButtons.size());
|
||||
mSpellButtons[mControllerFocus].first->setStateSelected(true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
if (mSpellButtons.size() <= 1)
|
||||
return true;
|
||||
|
||||
mSpellButtons[mControllerFocus].first->setStateSelected(false);
|
||||
mControllerFocus = wrap(mControllerFocus + 1, mSpellButtons.size());
|
||||
mSpellButtons[mControllerFocus].first->setStateSelected(true);
|
||||
}
|
||||
else
|
||||
return true;
|
||||
|
||||
if (mControllerFocus < mSpellButtons.size())
|
||||
{
|
||||
// Scroll the list to keep the active item in view
|
||||
size_t line = mSpellButtons[mControllerFocus].second;
|
||||
if (line <= 5)
|
||||
mSpellsView->setViewOffset(MyGUI::IntPoint(0, 0));
|
||||
else
|
||||
{
|
||||
const int lineHeight = Settings::gui().mFontSize + 2;
|
||||
mSpellsView->setViewOffset(MyGUI::IntPoint(0, -lineHeight * (line - 5)));
|
||||
}
|
||||
|
||||
// Warp the mouse to the selected spell to show the tooltip
|
||||
if (MWBase::Environment::get().getWindowManager()->getControllerTooltip())
|
||||
MWBase::Environment::get().getInputManager()->warpMouseToWidget(mSpellButtons[mControllerFocus].first);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ namespace MWGui
|
|||
MyGUI::ScrollView* mSpellsView;
|
||||
|
||||
std::map<MyGUI::Widget*, ESM::RefId> mSpellsWidgetMap;
|
||||
/// List of enabled/purchasable spells and their index in the full list.
|
||||
std::vector<std::pair<MyGUI::Button*, size_t>> mSpellButtons;
|
||||
|
||||
void onCancelButtonClicked(MyGUI::Widget* _sender);
|
||||
void onSpellButtonClick(MyGUI::Widget* _sender);
|
||||
|
|
@ -55,6 +57,8 @@ namespace MWGui
|
|||
|
||||
private:
|
||||
static bool sortSpells(const ESM::Spell* left, const ESM::Spell* right);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
size_t mControllerFocus;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,11 +7,13 @@
|
|||
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
#include <components/settings/values.hpp>
|
||||
#include <components/widgets/list.hpp>
|
||||
|
||||
#include <components/esm3/loadgmst.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
|
|
@ -25,8 +27,8 @@
|
|||
#include "../mwmechanics/spellutil.hpp"
|
||||
|
||||
#include "class.hpp"
|
||||
#include "textcolours.hpp"
|
||||
#include "tooltips.hpp"
|
||||
#include "widgets.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
@ -95,6 +97,13 @@ namespace MWGui
|
|||
+= MyGUI::newDelegate(this, &EditEffectDialog::onMagnitudeMaxChanged);
|
||||
mDurationSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &EditEffectDialog::onDurationChanged);
|
||||
mAreaSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &EditEffectDialog::onAreaChanged);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
mControllerButtons.mX = "#{Interface:OK}";
|
||||
}
|
||||
}
|
||||
|
||||
void EditEffectDialog::setConstantEffect(bool constant)
|
||||
|
|
@ -154,6 +163,15 @@ namespace MWGui
|
|||
mMagnitudeMaxValue->setCaption(to + " 1");
|
||||
mAreaValue->setCaption("0");
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mRangeButton->setStateSelected(true);
|
||||
mDeleteButton->setStateSelected(false);
|
||||
mOkButton->setStateSelected(false);
|
||||
mCancelButton->setStateSelected(false);
|
||||
mControllerFocus = 0;
|
||||
}
|
||||
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
|
|
@ -187,6 +205,15 @@ namespace MWGui
|
|||
onDurationChanged(mDurationSlider, effect.mDuration - 1);
|
||||
eventEffectModified(mEffect);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mRangeButton->setStateSelected(true);
|
||||
mDeleteButton->setStateSelected(false);
|
||||
mOkButton->setStateSelected(false);
|
||||
mCancelButton->setStateSelected(false);
|
||||
mControllerFocus = 0;
|
||||
}
|
||||
|
||||
updateBoxes();
|
||||
}
|
||||
|
||||
|
|
@ -231,6 +258,25 @@ namespace MWGui
|
|||
mAreaBox->setVisible(true);
|
||||
// curY += mAreaBox->getSize().height;
|
||||
}
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mButtons.clear();
|
||||
mButtons.emplace_back(mRangeButton);
|
||||
if (mMagnitudeBox->getVisible())
|
||||
{
|
||||
mButtons.emplace_back(mMagnitudeMinValue);
|
||||
mButtons.emplace_back(mMagnitudeMaxValue);
|
||||
}
|
||||
if (mDurationBox->getVisible())
|
||||
mButtons.emplace_back(mDurationValue);
|
||||
if (mAreaBox->getVisible())
|
||||
mButtons.emplace_back(mAreaValue);
|
||||
if (mDeleteButton->getVisible())
|
||||
mButtons.emplace_back(mDeleteButton);
|
||||
mButtons.emplace_back(mOkButton);
|
||||
mButtons.emplace_back(mCancelButton);
|
||||
}
|
||||
}
|
||||
|
||||
void EditEffectDialog::onRangeButtonClicked(MyGUI::Widget* sender)
|
||||
|
|
@ -340,6 +386,195 @@ namespace MWGui
|
|||
eventEffectModified(mEffect);
|
||||
}
|
||||
|
||||
bool EditEffectDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
int prevFocus = mControllerFocus;
|
||||
mControllerFocus = std::clamp(mControllerFocus, 0, static_cast<int>(mButtons.size()) - 1);
|
||||
MyGUI::TextBox* button = mButtons[mControllerFocus];
|
||||
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (button == mRangeButton)
|
||||
onRangeButtonClicked(mRangeButton);
|
||||
else if (button == mCancelButton)
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
else if (button == mOkButton)
|
||||
onOkButtonClicked(mOkButton);
|
||||
else if (button == mDeleteButton)
|
||||
onDeleteButtonClicked(mDeleteButton);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
{
|
||||
onOkButtonClicked(mOkButton);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
if (mControllerFocus == 0)
|
||||
mControllerFocus = static_cast<int>(mButtons.size()) - 2;
|
||||
else if (button == mCancelButton && mDeleteButton->getVisible())
|
||||
mControllerFocus -= 3;
|
||||
else if (button == mCancelButton || (button == mOkButton && mDeleteButton->getVisible()))
|
||||
mControllerFocus -= 2;
|
||||
else
|
||||
mControllerFocus = std::max(mControllerFocus - 1, 0);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
if (button == mDeleteButton || button == mOkButton || button == mCancelButton)
|
||||
mControllerFocus = 0;
|
||||
else
|
||||
mControllerFocus++;
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
|
||||
{
|
||||
if (button == mMagnitudeMinValue)
|
||||
{
|
||||
mMagnitudeMinSlider->setScrollPosition(0);
|
||||
onMagnitudeMinChanged(nullptr, mMagnitudeMinSlider->getScrollPosition());
|
||||
}
|
||||
else if (button == mMagnitudeMaxValue)
|
||||
{
|
||||
mMagnitudeMaxSlider->setScrollPosition(mMagnitudeMinSlider->getScrollPosition());
|
||||
onMagnitudeMaxChanged(nullptr, mMagnitudeMaxSlider->getScrollPosition());
|
||||
}
|
||||
else if (button == mDurationValue)
|
||||
{
|
||||
mDurationSlider->setScrollPosition(0);
|
||||
onDurationChanged(nullptr, mDurationSlider->getScrollPosition());
|
||||
}
|
||||
else if (button == mAreaValue)
|
||||
{
|
||||
mAreaSlider->setScrollPosition(0);
|
||||
onAreaChanged(nullptr, mAreaSlider->getScrollPosition());
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
|
||||
{
|
||||
if (button == mMagnitudeMinValue)
|
||||
{
|
||||
mMagnitudeMinSlider->setScrollPosition(mMagnitudeMaxSlider->getScrollPosition());
|
||||
onMagnitudeMinChanged(nullptr, mMagnitudeMinSlider->getScrollPosition());
|
||||
}
|
||||
else if (button == mMagnitudeMaxValue)
|
||||
{
|
||||
mMagnitudeMaxSlider->setScrollPosition(mMagnitudeMaxSlider->getScrollRange() - 1);
|
||||
onMagnitudeMaxChanged(nullptr, mMagnitudeMaxSlider->getScrollPosition());
|
||||
}
|
||||
else if (button == mDurationValue)
|
||||
{
|
||||
mDurationSlider->setScrollPosition(mDurationSlider->getScrollRange() - 1);
|
||||
onDurationChanged(nullptr, mDurationSlider->getScrollPosition());
|
||||
}
|
||||
else if (button == mAreaValue)
|
||||
{
|
||||
mAreaSlider->setScrollPosition(mAreaSlider->getScrollRange() - 1);
|
||||
onAreaChanged(nullptr, mAreaSlider->getScrollPosition());
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
|
||||
{
|
||||
if (button == mRangeButton)
|
||||
onRangeButtonClicked(mRangeButton);
|
||||
else if (button == mCancelButton)
|
||||
mControllerFocus--;
|
||||
else if (button == mOkButton && mDeleteButton->getVisible())
|
||||
mControllerFocus--;
|
||||
else if (button == mMagnitudeMinValue)
|
||||
{
|
||||
mMagnitudeMinSlider->setScrollPosition(mMagnitudeMinSlider->getScrollPosition() - 1);
|
||||
onMagnitudeMinChanged(nullptr, mMagnitudeMinSlider->getScrollPosition());
|
||||
}
|
||||
else if (button == mMagnitudeMaxValue)
|
||||
{
|
||||
mMagnitudeMaxSlider->setScrollPosition(
|
||||
std::max(mMagnitudeMaxSlider->getScrollPosition() - 1, mMagnitudeMinSlider->getScrollPosition()));
|
||||
onMagnitudeMaxChanged(nullptr, mMagnitudeMaxSlider->getScrollPosition());
|
||||
}
|
||||
else if (button == mDurationValue)
|
||||
{
|
||||
mDurationSlider->setScrollPosition(mDurationSlider->getScrollPosition() - 1);
|
||||
onDurationChanged(nullptr, mDurationSlider->getScrollPosition());
|
||||
}
|
||||
else if (button == mAreaValue)
|
||||
{
|
||||
mAreaSlider->setScrollPosition(mAreaSlider->getScrollPosition() - 1);
|
||||
onAreaChanged(nullptr, mAreaSlider->getScrollPosition());
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
|
||||
{
|
||||
if (button == mRangeButton)
|
||||
onRangeButtonClicked(mRangeButton);
|
||||
else if (button == mDeleteButton)
|
||||
mControllerFocus++;
|
||||
else if (button == mOkButton)
|
||||
mControllerFocus++;
|
||||
else if (button == mMagnitudeMinValue)
|
||||
{
|
||||
mMagnitudeMinSlider->setScrollPosition(
|
||||
std::min(mMagnitudeMinSlider->getScrollPosition() + 1, mMagnitudeMaxSlider->getScrollPosition()));
|
||||
onMagnitudeMinChanged(nullptr, mMagnitudeMinSlider->getScrollPosition());
|
||||
}
|
||||
else if (button == mMagnitudeMaxValue)
|
||||
{
|
||||
mMagnitudeMaxSlider->setScrollPosition(mMagnitudeMaxSlider->getScrollPosition() + 1);
|
||||
onMagnitudeMaxChanged(nullptr, mMagnitudeMaxSlider->getScrollPosition());
|
||||
}
|
||||
else if (button == mDurationValue)
|
||||
{
|
||||
mDurationSlider->setScrollPosition(mDurationSlider->getScrollPosition() + 1);
|
||||
onDurationChanged(nullptr, mDurationSlider->getScrollPosition());
|
||||
}
|
||||
else if (button == mAreaValue)
|
||||
{
|
||||
mAreaSlider->setScrollPosition(mAreaSlider->getScrollPosition() + 1);
|
||||
onAreaChanged(nullptr, mAreaSlider->getScrollPosition());
|
||||
}
|
||||
}
|
||||
|
||||
if (prevFocus != mControllerFocus)
|
||||
updateControllerFocus(prevFocus, mControllerFocus);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EditEffectDialog::updateControllerFocus(int prevFocus, int newFocus)
|
||||
{
|
||||
const TextColours& textColours{ MWBase::Environment::get().getWindowManager()->getTextColours() };
|
||||
|
||||
if (prevFocus >= 0 && prevFocus < static_cast<int>(mButtons.size()))
|
||||
{
|
||||
MyGUI::TextBox* button = mButtons[prevFocus];
|
||||
if (button == mMagnitudeMinValue || button == mMagnitudeMaxValue || button == mDurationValue
|
||||
|| button == mAreaValue)
|
||||
{
|
||||
button->setTextColour(textColours.normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_cast<MyGUI::Button*>(button)->setStateSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (newFocus >= 0 && newFocus < static_cast<int>(mButtons.size()))
|
||||
{
|
||||
MyGUI::TextBox* button = mButtons[newFocus];
|
||||
if (button == mMagnitudeMinValue || button == mMagnitudeMaxValue || button == mDurationValue
|
||||
|| button == mAreaValue)
|
||||
{
|
||||
button->setTextColour(textColours.link);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_cast<MyGUI::Button*>(button)->setStateSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
SpellCreationDialog::SpellCreationDialog()
|
||||
|
|
@ -361,6 +596,14 @@ namespace MWGui
|
|||
mNameEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &SpellCreationDialog::onAccept);
|
||||
|
||||
setWidgets(mAvailableEffectsList, mUsedEffectsView);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
mControllerButtons.mX = "#{sBuy}";
|
||||
mControllerButtons.mR3 = "#{sInfo}";
|
||||
}
|
||||
}
|
||||
|
||||
void SpellCreationDialog::setPtr(const MWWorld::Ptr& actor)
|
||||
|
|
@ -495,6 +738,22 @@ namespace MWGui
|
|||
mSuccessChance->setCaption(MyGUI::utility::toString(intChance));
|
||||
}
|
||||
|
||||
bool SpellCreationDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
return true;
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
|
||||
{
|
||||
onBuyButtonClicked(mBuyButton);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return EffectEditorBase::onControllerButtonEvent(arg);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
EffectEditorBase::EffectEditorBase(Type type)
|
||||
|
|
@ -566,6 +825,7 @@ namespace MWGui
|
|||
mAvailableEffectsList->adjustSize();
|
||||
mAvailableEffectsList->scrollToTop();
|
||||
|
||||
mAvailableButtons.clear();
|
||||
for (const short effectId : knownEffects)
|
||||
{
|
||||
const std::string& name = MWBase::Environment::get()
|
||||
|
|
@ -573,13 +833,27 @@ namespace MWGui
|
|||
->get<ESM::GameSetting>()
|
||||
.find(ESM::MagicEffect::indexToGmstString(effectId))
|
||||
->mValue.getString();
|
||||
MyGUI::Widget* w = mAvailableEffectsList->getItemWidget(name);
|
||||
MyGUI::Button* w = mAvailableEffectsList->getItemWidget(name);
|
||||
mAvailableButtons.emplace_back(w);
|
||||
|
||||
ToolTips::createMagicEffectToolTip(w, effectId);
|
||||
}
|
||||
|
||||
mEffects.clear();
|
||||
updateEffectsView();
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mAvailableFocus = 0;
|
||||
mEffectFocus = 0;
|
||||
mRightColumn = false;
|
||||
if (mAvailableButtons.size() > 0)
|
||||
{
|
||||
mAvailableButtons[0]->setStateSelected(true);
|
||||
if (MWBase::Environment::get().getWindowManager()->getControllerTooltip())
|
||||
MWBase::Environment::get().getInputManager()->warpMouseToWidget(mAvailableButtons[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EffectEditorBase::setWidgets(Gui::MWList* availableEffectsList, MyGUI::ScrollView* usedEffectsView)
|
||||
|
|
@ -691,6 +965,7 @@ namespace MWGui
|
|||
|
||||
MyGUI::IntSize size(0, 0);
|
||||
|
||||
mEffectButtons.clear();
|
||||
int i = 0;
|
||||
for (const ESM::ENAMstruct& effectInfo : mEffects)
|
||||
{
|
||||
|
|
@ -723,6 +998,8 @@ namespace MWGui
|
|||
size.width = std::max(size.width, effect->getRequestedWidth());
|
||||
size.height += 24;
|
||||
++i;
|
||||
|
||||
mEffectButtons.emplace_back(std::pair(effect, button));
|
||||
}
|
||||
|
||||
// Canvas size must be expressed with HScroll disabled, otherwise MyGUI would expand the scroll area when the
|
||||
|
|
@ -760,4 +1037,102 @@ namespace MWGui
|
|||
effect.mRange = ESM::RT_Self;
|
||||
mConstantEffect = constant;
|
||||
}
|
||||
|
||||
bool EffectEditorBase::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (!mRightColumn && mAvailableFocus >= 0 && mAvailableFocus < static_cast<int>(mAvailableButtons.size()))
|
||||
{
|
||||
onAvailableEffectClicked(mAvailableButtons[mAvailableFocus]);
|
||||
winMgr->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
else if (mRightColumn && mEffectFocus >= 0 && mEffectFocus < static_cast<int>(mEffectButtons.size()))
|
||||
{
|
||||
onEditEffect(mEffectButtons[mEffectFocus].second);
|
||||
winMgr->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSTICK)
|
||||
{
|
||||
// Toggle info tooltip
|
||||
winMgr->setControllerTooltip(!mRightColumn && !winMgr->getControllerTooltip());
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
if (mRightColumn && mEffectButtons.size() > 0)
|
||||
{
|
||||
if (mEffectFocus >= 0 && mEffectFocus < static_cast<int>(mEffectButtons.size()))
|
||||
mEffectButtons[mEffectFocus].first->setStateSelected(false);
|
||||
mEffectFocus = wrap(mEffectFocus - 1, mEffectButtons.size());
|
||||
mEffectButtons[mEffectFocus].first->setStateSelected(true);
|
||||
}
|
||||
else if (!mRightColumn && mAvailableButtons.size() > 0)
|
||||
{
|
||||
if (mAvailableFocus >= 0 && mAvailableFocus < static_cast<int>(mAvailableButtons.size()))
|
||||
mAvailableButtons[mAvailableFocus]->setStateSelected(false);
|
||||
mAvailableFocus = wrap(mAvailableFocus - 1, mAvailableButtons.size());
|
||||
mAvailableButtons[mAvailableFocus]->setStateSelected(true);
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
if (mRightColumn && mEffectButtons.size() > 0)
|
||||
{
|
||||
if (mEffectFocus >= 0 && mEffectFocus < static_cast<int>(mEffectButtons.size()))
|
||||
mEffectButtons[mEffectFocus].first->setStateSelected(false);
|
||||
mEffectFocus = wrap(mEffectFocus + 1, mEffectButtons.size());
|
||||
mEffectButtons[mEffectFocus].first->setStateSelected(true);
|
||||
}
|
||||
else if (!mRightColumn && mAvailableButtons.size() > 0)
|
||||
{
|
||||
if (mAvailableFocus >= 0 && mAvailableFocus < static_cast<int>(mAvailableButtons.size()))
|
||||
mAvailableButtons[mAvailableFocus]->setStateSelected(false);
|
||||
mAvailableFocus = wrap(mAvailableFocus + 1, mAvailableButtons.size());
|
||||
mAvailableButtons[mAvailableFocus]->setStateSelected(true);
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT && mRightColumn)
|
||||
{
|
||||
mRightColumn = false;
|
||||
if (mEffectFocus >= 0 && mEffectFocus < static_cast<int>(mEffectButtons.size()))
|
||||
mEffectButtons[mEffectFocus].first->setStateSelected(false);
|
||||
if (mAvailableFocus >= 0 && mAvailableFocus < static_cast<int>(mAvailableButtons.size()))
|
||||
mAvailableButtons[mAvailableFocus]->setStateSelected(true);
|
||||
|
||||
winMgr->setControllerTooltip(Settings::gui().mControllerTooltips);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT && !mRightColumn && mEffectButtons.size() > 0)
|
||||
{
|
||||
mRightColumn = true;
|
||||
if (mAvailableFocus >= 0 && mAvailableFocus < static_cast<int>(mAvailableButtons.size()))
|
||||
mAvailableButtons[mAvailableFocus]->setStateSelected(false);
|
||||
if (mEffectFocus >= 0 && mEffectFocus < static_cast<int>(mEffectButtons.size()))
|
||||
mEffectButtons[mEffectFocus].first->setStateSelected(true);
|
||||
|
||||
winMgr->setControllerTooltip(false);
|
||||
}
|
||||
else
|
||||
return true;
|
||||
|
||||
// Scroll the list to keep the active item in view
|
||||
if (mAvailableFocus <= 5)
|
||||
mAvailableEffectsList->setViewOffset(0);
|
||||
else
|
||||
{
|
||||
const int lineHeight = Settings::gui().mFontSize + 3;
|
||||
mAvailableEffectsList->setViewOffset(-lineHeight * (mAvailableFocus - 5));
|
||||
}
|
||||
|
||||
if (!mRightColumn && mAvailableFocus >= 0 && mAvailableFocus < static_cast<int>(mAvailableButtons.size()))
|
||||
{
|
||||
// Warp the mouse to the selected spell to show the tooltip
|
||||
if (winMgr->getControllerTooltip())
|
||||
MWBase::Environment::get().getInputManager()->warpMouseToWidget(mAvailableButtons[mAvailableFocus]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <components/esm3/loadspel.hpp>
|
||||
|
||||
#include "referenceinterface.hpp"
|
||||
#include "widgets.hpp"
|
||||
#include "windowbase.hpp"
|
||||
|
||||
namespace Gui
|
||||
|
|
@ -83,13 +84,18 @@ namespace MWGui
|
|||
|
||||
void updateBoxes();
|
||||
|
||||
protected:
|
||||
private:
|
||||
ESM::ENAMstruct mEffect;
|
||||
ESM::ENAMstruct mOldEffect;
|
||||
|
||||
const ESM::MagicEffect* mMagicEffect;
|
||||
|
||||
bool mConstantEffect;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
void updateControllerFocus(int prevFocus, int newFocus);
|
||||
int mControllerFocus;
|
||||
std::vector<MyGUI::TextBox*> mButtons;
|
||||
};
|
||||
|
||||
class EffectEditorBase
|
||||
|
|
@ -142,8 +148,16 @@ namespace MWGui
|
|||
|
||||
virtual void notifyEffectsChanged() {}
|
||||
|
||||
virtual bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg);
|
||||
|
||||
private:
|
||||
Type mType;
|
||||
|
||||
int mAvailableFocus;
|
||||
int mEffectFocus;
|
||||
bool mRightColumn;
|
||||
std::vector<MyGUI::Button*> mAvailableButtons;
|
||||
std::vector<std::pair<Widgets::MWSpellEffectPtr, MyGUI::Button*>> mEffectButtons;
|
||||
};
|
||||
|
||||
class SpellCreationDialog : public WindowBase, public ReferenceInterface, public EffectEditorBase
|
||||
|
|
@ -166,6 +180,7 @@ namespace MWGui
|
|||
void onCancelButtonClicked(MyGUI::Widget* sender);
|
||||
void onBuyButtonClicked(MyGUI::Widget* sender);
|
||||
void onAccept(MyGUI::EditBox* sender);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
|
||||
void notifyEffectsChanged() override;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,12 @@
|
|||
#include <components/widgets/box.hpp>
|
||||
#include <components/widgets/sharedstatebutton.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include "tooltips.hpp"
|
||||
#include "windowbase.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
|
@ -28,6 +33,8 @@ namespace MWGui
|
|||
: mScrollView(nullptr)
|
||||
, mShowCostColumn(true)
|
||||
, mHighlightSelected(true)
|
||||
, mControllerActiveWindow(false)
|
||||
, mControllerFocus(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +95,8 @@ namespace MWGui
|
|||
const int spellHeight = Settings::gui().mFontSize + 2;
|
||||
|
||||
mLines.clear();
|
||||
mButtons.clear();
|
||||
mGroupIndices.clear();
|
||||
|
||||
while (mScrollView->getChildCount())
|
||||
MyGUI::Gui::getInstance().destroyWidget(mScrollView->getChildAt(0));
|
||||
|
|
@ -106,7 +115,9 @@ namespace MWGui
|
|||
curType = spell.mType;
|
||||
}
|
||||
|
||||
const std::string skin = spell.mActive ? "SandTextButton" : "SpellTextUnequipped";
|
||||
std::string skin = spell.mActive ? "SandTextButton" : "SpellTextUnequipped";
|
||||
if (Settings::gui().mControllerMenus)
|
||||
skin = spell.mActive ? "SpellTextEquippedController" : "SpellTextUnequippedController";
|
||||
const std::string captionSuffix = MWGui::ToolTips::getCountString(spell.mCount);
|
||||
|
||||
Gui::SharedStateButton* t = mScrollView->createWidget<Gui::SharedStateButton>(
|
||||
|
|
@ -115,6 +126,7 @@ namespace MWGui
|
|||
t->setCaption(spell.mName + captionSuffix);
|
||||
t->setTextAlign(MyGUI::Align::Left);
|
||||
adjustSpellWidget(spell, i, t);
|
||||
mButtons.emplace_back(std::make_pair(t, i));
|
||||
|
||||
if (!spell.mCostColumn.empty() && mShowCostColumn)
|
||||
{
|
||||
|
|
@ -132,7 +144,7 @@ namespace MWGui
|
|||
mLines.emplace_back(t, costChance, i);
|
||||
}
|
||||
else
|
||||
mLines.emplace_back(t, (MyGUI::Widget*)nullptr, i);
|
||||
mLines.emplace_back(t, static_cast<MyGUI::Widget*>(nullptr), i);
|
||||
|
||||
t->setStateSelected(spell.mSelected);
|
||||
}
|
||||
|
|
@ -221,6 +233,12 @@ namespace MWGui
|
|||
height += lineHeight;
|
||||
}
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerFocus = wrap(mControllerFocus, mButtons.size());
|
||||
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);
|
||||
|
|
@ -235,7 +253,7 @@ namespace MWGui
|
|||
MyGUI::ImageBox* separator = mScrollView->createWidget<MyGUI::ImageBox>(
|
||||
"MW_HLine", MyGUI::IntCoord(0, 0, mScrollView->getWidth(), 18), MyGUI::Align::Left | MyGUI::Align::Top);
|
||||
separator->setNeedMouseFocus(false);
|
||||
mLines.emplace_back(separator, (MyGUI::Widget*)nullptr, NoSpellIndex);
|
||||
mLines.emplace_back(separator, static_cast<MyGUI::Widget*>(nullptr), NoSpellIndex);
|
||||
}
|
||||
|
||||
MyGUI::TextBox* groupWidget = mScrollView->createWidget<Gui::TextBox>("SandBrightText",
|
||||
|
|
@ -255,7 +273,9 @@ namespace MWGui
|
|||
mLines.emplace_back(groupWidget, groupWidget2, NoSpellIndex);
|
||||
}
|
||||
else
|
||||
mLines.emplace_back(groupWidget, (MyGUI::Widget*)nullptr, NoSpellIndex);
|
||||
mLines.emplace_back(groupWidget, static_cast<MyGUI::Widget*>(nullptr), NoSpellIndex);
|
||||
|
||||
mGroupIndices.push_back(mButtons.size());
|
||||
}
|
||||
|
||||
void SpellView::setSize(const MyGUI::IntSize& _value)
|
||||
|
|
@ -316,4 +336,124 @@ namespace MWGui
|
|||
{
|
||||
mScrollView->setViewOffset(MyGUI::IntPoint(0, 0));
|
||||
}
|
||||
|
||||
void SpellView::setActiveControllerWindow(bool active)
|
||||
{
|
||||
mControllerActiveWindow = active;
|
||||
if (active)
|
||||
update();
|
||||
}
|
||||
|
||||
void SpellView::onControllerButton(const unsigned char button)
|
||||
{
|
||||
if (mButtons.empty())
|
||||
return;
|
||||
|
||||
int prevFocus = mControllerFocus;
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case SDL_CONTROLLER_BUTTON_A:
|
||||
// Select the focused item, if any.
|
||||
if (mControllerFocus >= 0 && mControllerFocus < static_cast<int>(mButtons.size()))
|
||||
{
|
||||
onSpellSelected(mButtons[mControllerFocus].first);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
|
||||
// Toggle info tooltip
|
||||
MWBase::Environment::get().getWindowManager()->setControllerTooltip(
|
||||
!MWBase::Environment::get().getWindowManager()->getControllerTooltip());
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_UP:
|
||||
mControllerFocus--;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
|
||||
mControllerFocus++;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
|
||||
mControllerFocus = std::max(0, mControllerFocus - 10);
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
|
||||
mControllerFocus = std::min(mControllerFocus + 10, static_cast<int>(mButtons.size()) - 1);
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
|
||||
{
|
||||
// Jump to first item in previous group
|
||||
int prevGroupIndex = 0;
|
||||
for (int groupIndex : mGroupIndices)
|
||||
{
|
||||
if (groupIndex >= mControllerFocus)
|
||||
break;
|
||||
else
|
||||
prevGroupIndex = groupIndex;
|
||||
}
|
||||
mControllerFocus = prevGroupIndex;
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
|
||||
{
|
||||
// Jump to first item in next group
|
||||
int newFocus = mControllerFocus;
|
||||
for (int groupIndex : mGroupIndices)
|
||||
{
|
||||
if (groupIndex > mControllerFocus)
|
||||
{
|
||||
newFocus = groupIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If on last group, jump to bottom of whole list
|
||||
if (newFocus == mControllerFocus)
|
||||
newFocus = mButtons.size() - 1;
|
||||
mControllerFocus = newFocus;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
mControllerFocus = wrap(mControllerFocus, mButtons.size());
|
||||
|
||||
if (prevFocus != mControllerFocus)
|
||||
updateControllerFocus(prevFocus, mControllerFocus);
|
||||
else
|
||||
updateControllerFocus(-1, mControllerFocus);
|
||||
}
|
||||
|
||||
void SpellView::updateControllerFocus(int prevFocus, int newFocus)
|
||||
{
|
||||
if (mButtons.empty())
|
||||
return;
|
||||
|
||||
if (prevFocus >= 0 && prevFocus < static_cast<int>(mButtons.size()))
|
||||
{
|
||||
Gui::SharedStateButton* prev = mButtons[prevFocus].first;
|
||||
if (prev)
|
||||
prev->onMouseLostFocus(nullptr);
|
||||
}
|
||||
|
||||
if (mControllerActiveWindow && newFocus >= 0 && newFocus < static_cast<int>(mButtons.size()))
|
||||
{
|
||||
Gui::SharedStateButton* focused = mButtons[newFocus].first;
|
||||
if (focused)
|
||||
{
|
||||
focused->onMouseSetFocus(nullptr);
|
||||
|
||||
// Scroll the list to keep the active item in view
|
||||
int line = mButtons[newFocus].second;
|
||||
if (line <= 5)
|
||||
mScrollView->setViewOffset(MyGUI::IntPoint(0, 0));
|
||||
else
|
||||
{
|
||||
const int lineHeight = focused->getHeight();
|
||||
mScrollView->setViewOffset(MyGUI::IntPoint(0, -lineHeight * (line - 5)));
|
||||
}
|
||||
|
||||
if (MWBase::Environment::get().getWindowManager()->getControllerTooltip())
|
||||
MWBase::Environment::get().getInputManager()->warpMouseToWidget(focused);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@ namespace MyGUI
|
|||
class ScrollView;
|
||||
}
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
class SharedStateButton;
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
||||
|
|
@ -54,6 +59,9 @@ namespace MWGui
|
|||
|
||||
void resetScrollbars();
|
||||
|
||||
void setActiveControllerWindow(bool active);
|
||||
void onControllerButton(const unsigned char button);
|
||||
|
||||
private:
|
||||
MyGUI::ScrollView* mScrollView;
|
||||
|
||||
|
|
@ -89,6 +97,15 @@ namespace MWGui
|
|||
void addGroup(const std::string& label1, const std::string& label2);
|
||||
void adjustSpellWidget(const Spell& spell, SpellModel::ModelIndex index, MyGUI::Widget* widget);
|
||||
|
||||
/// Keep a list of buttons for controller navigation and their index in the full list.
|
||||
std::vector<std::pair<Gui::SharedStateButton*, int>> mButtons;
|
||||
/// Keep a list of group offsets for controller navigation
|
||||
std::vector<int> mGroupIndices;
|
||||
|
||||
bool mControllerActiveWindow;
|
||||
int mControllerFocus;
|
||||
void updateControllerFocus(int prevFocus, int newFocus);
|
||||
|
||||
void onSpellSelected(MyGUI::Widget* _sender);
|
||||
void onMouseWheelMoved(MyGUI::Widget* _sender, int _rel);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <MyGUI_EditBox.h>
|
||||
#include <MyGUI_InputManager.h>
|
||||
#include <MyGUI_RenderManager.h>
|
||||
#include <MyGUI_Window.h>
|
||||
|
||||
#include <components/esm3/loadbsgn.hpp>
|
||||
#include <components/esm3/loadrace.hpp>
|
||||
|
|
@ -27,6 +29,7 @@
|
|||
#include "confirmationdialog.hpp"
|
||||
#include "spellicons.hpp"
|
||||
#include "spellview.hpp"
|
||||
#include "statswindow.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
|
@ -55,6 +58,14 @@ namespace MWGui
|
|||
// Adjust the spell filtering widget size because of MyGUI limitations.
|
||||
int filterWidth = mSpellView->getSize().width - deleteButton->getSize().width - 3;
|
||||
mFilterEdit->setSize(filterWidth, mFilterEdit->getSize().height);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
setPinButtonVisible(false);
|
||||
mControllerButtons.mA = "#{sSelect}";
|
||||
mControllerButtons.mB = "#{sBack}";
|
||||
mControllerButtons.mR3 = "#{sInfo}";
|
||||
}
|
||||
}
|
||||
|
||||
void SpellWindow::onPinToggled()
|
||||
|
|
@ -66,7 +77,9 @@ namespace MWGui
|
|||
|
||||
void SpellWindow::onTitleDoubleClicked()
|
||||
{
|
||||
if (MyGUI::InputManager::getInstance().isShiftPressed())
|
||||
if (Settings::gui().mControllerMenus)
|
||||
return;
|
||||
else if (MyGUI::InputManager::getInstance().isShiftPressed())
|
||||
MWBase::Environment::get().getWindowManager()->toggleMaximized(this);
|
||||
else if (!mPinned)
|
||||
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Magic);
|
||||
|
|
@ -288,4 +301,39 @@ namespace MWGui
|
|||
onSpellSelected(selectedSpell.mId);
|
||||
}
|
||||
}
|
||||
|
||||
bool SpellWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
|
||||
else
|
||||
mSpellView->onControllerButton(arg.button);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpellWindow::setActiveControllerWindow(bool active)
|
||||
{
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
if (winMgr->getMode() == MWGui::GM_Inventory)
|
||||
{
|
||||
// Fill the screen, or limit to a certain size on large screens. Size chosen to
|
||||
// match the size of the stats window.
|
||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
int width = std::min(viewSize.width, StatsWindow::getIdealWidth());
|
||||
int height = std::min(winMgr->getControllerMenuHeight(), StatsWindow::getIdealHeight());
|
||||
int x = (viewSize.width - width) / 2;
|
||||
int y = (viewSize.height - height) / 2;
|
||||
|
||||
MyGUI::Window* window = mMainWidget->castType<MyGUI::Window>();
|
||||
window->setCoord(x, active ? y : viewSize.height + 1, width, height);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setControllerTooltip(
|
||||
active && Settings::gui().mControllerTooltips);
|
||||
}
|
||||
|
||||
mSpellView->setActiveControllerWindow(active);
|
||||
|
||||
WindowBase::setActiveControllerWindow(active);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ namespace MWGui
|
|||
void onPinToggled() override;
|
||||
void onTitleDoubleClicked() override;
|
||||
void onOpen() override;
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
void setActiveControllerWindow(bool active) override;
|
||||
|
||||
SpellView* mSpellView;
|
||||
std::unique_ptr<SpellIcons> mSpellIcons;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <MyGUI_InputManager.h>
|
||||
#include <MyGUI_LanguageManager.h>
|
||||
#include <MyGUI_ProgressBar.h>
|
||||
#include <MyGUI_RenderManager.h>
|
||||
#include <MyGUI_ScrollView.h>
|
||||
#include <MyGUI_TextIterator.h>
|
||||
#include <MyGUI_Window.h>
|
||||
|
|
@ -80,6 +81,14 @@ namespace MWGui
|
|||
MyGUI::Window* t = mMainWidget->castType<MyGUI::Window>();
|
||||
t->eventWindowChangeCoord += MyGUI::newDelegate(this, &StatsWindow::onWindowResize);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
setPinButtonVisible(false);
|
||||
mControllerButtons.mLStick = "#{sMouse}";
|
||||
mControllerButtons.mRStick = "#{sScrolldown}";
|
||||
mControllerButtons.mB = "#{sBack}";
|
||||
}
|
||||
|
||||
onWindowResize(t);
|
||||
}
|
||||
|
||||
|
|
@ -714,7 +723,9 @@ namespace MWGui
|
|||
|
||||
void StatsWindow::onTitleDoubleClicked()
|
||||
{
|
||||
if (MyGUI::InputManager::getInstance().isShiftPressed())
|
||||
if (Settings::gui().mControllerMenus)
|
||||
return;
|
||||
else if (MyGUI::InputManager::getInstance().isShiftPressed())
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->toggleMaximized(this);
|
||||
MyGUI::Window* t = mMainWidget->castType<MyGUI::Window>();
|
||||
|
|
@ -723,4 +734,35 @@ namespace MWGui
|
|||
else if (!mPinned)
|
||||
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Stats);
|
||||
}
|
||||
|
||||
bool StatsWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void StatsWindow::setActiveControllerWindow(bool active)
|
||||
{
|
||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||
if (winMgr->getMode() == MWGui::GM_Inventory)
|
||||
{
|
||||
// Fill the screen, or limit to a certain size on large screens. Size chosen to
|
||||
// show all stats.
|
||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
int width = std::min(viewSize.width, getIdealWidth());
|
||||
int height = std::min(winMgr->getControllerMenuHeight(), getIdealHeight());
|
||||
int x = (viewSize.width - width) / 2;
|
||||
int y = (viewSize.height - height) / 2;
|
||||
|
||||
MyGUI::Window* window = mMainWidget->castType<MyGUI::Window>();
|
||||
window->setCoord(x, active ? y : viewSize.height + 1, width, height);
|
||||
|
||||
if (active)
|
||||
onWindowResize(window);
|
||||
}
|
||||
|
||||
WindowBase::setActiveControllerWindow(active);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@ namespace MWGui
|
|||
public:
|
||||
typedef std::map<ESM::RefId, int> FactionList;
|
||||
|
||||
/// It would be nice to measure these, but for now they're hardcoded.
|
||||
static int getIdealHeight() { return 750; }
|
||||
static int getIdealWidth() { return 600; }
|
||||
|
||||
StatsWindow(DragAndDrop* drag);
|
||||
|
||||
/// automatically updates all the data in the stats window, but only if it has changed.
|
||||
|
|
@ -47,6 +51,10 @@ namespace MWGui
|
|||
|
||||
std::string_view getWindowIdForLua() const override { return "Stats"; }
|
||||
|
||||
protected:
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
void setActiveControllerWindow(bool active) override;
|
||||
|
||||
private:
|
||||
void addSkills(const std::vector<ESM::RefId>& skills, const std::string& titleId,
|
||||
const std::string& titleDefault, MyGUI::IntCoord& coord1, MyGUI::IntCoord& coord2);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#include <MyGUI_EditBox.h>
|
||||
#include <MyGUI_UString.h>
|
||||
|
||||
#include <components/esm/refid.hpp>
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
||||
|
|
@ -25,6 +27,8 @@ namespace MWGui
|
|||
|
||||
// Make sure the edit box has focus
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit);
|
||||
|
||||
mControllerButtons.mA = "#{Interface:OK}";
|
||||
}
|
||||
|
||||
void TextInputDialog::setNextButtonShow(bool shown)
|
||||
|
|
@ -83,4 +87,15 @@ namespace MWGui
|
|||
mTextEdit->setCaption(text);
|
||||
}
|
||||
|
||||
bool TextInputDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
onOkClicked(nullptr);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ namespace MWGui
|
|||
protected:
|
||||
void onOkClicked(MyGUI::Widget* _sender);
|
||||
void onTextAccepted(MyGUI::EditBox* _sender);
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
|
||||
private:
|
||||
MyGUI::EditBox* mTextEdit;
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ namespace MWGui
|
|||
|
||||
if (guiMode)
|
||||
{
|
||||
if (!winMgr->getCursorVisible())
|
||||
if (!winMgr->getCursorVisible() && !winMgr->getControllerTooltip())
|
||||
return;
|
||||
const MyGUI::IntPoint& mousePos = MyGUI::InputManager::getInstance().getMousePosition();
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <MyGUI_Button.h>
|
||||
#include <MyGUI_ControllerManager.h>
|
||||
#include <MyGUI_ControllerRepeatClick.h>
|
||||
#include <MyGUI_ImageBox.h>
|
||||
#include <MyGUI_InputManager.h>
|
||||
|
||||
#include <components/misc/rng.hpp>
|
||||
|
|
@ -11,6 +12,7 @@
|
|||
|
||||
#include "../mwbase/dialoguemanager.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
|
@ -169,6 +171,29 @@ namespace MWGui
|
|||
std::numeric_limits<int>::min() + 1); // disallow INT_MIN since abs(INT_MIN) is undefined
|
||||
|
||||
setCoord(400, 0, 400, 300);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
// Show L1 and R1 buttons next to tabs
|
||||
MyGUI::ImageBox* image;
|
||||
getWidget(image, "BtnL1Image");
|
||||
image->setVisible(true);
|
||||
image->setUserString("Hidden", "false");
|
||||
image->setImageTexture(MWBase::Environment::get().getInputManager()->getControllerButtonIcon(
|
||||
SDL_CONTROLLER_BUTTON_LEFTSHOULDER));
|
||||
|
||||
getWidget(image, "BtnR1Image");
|
||||
image->setVisible(true);
|
||||
image->setUserString("Hidden", "false");
|
||||
image->setImageTexture(MWBase::Environment::get().getInputManager()->getControllerButtonIcon(
|
||||
SDL_CONTROLLER_BUTTON_RIGHTSHOULDER));
|
||||
|
||||
mControllerButtons.mA = "#{sBuy}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
mControllerButtons.mX = "#{sOffer}";
|
||||
mControllerButtons.mR3 = "#{sInfo}";
|
||||
mControllerButtons.mL2 = "#{sInventory}";
|
||||
}
|
||||
}
|
||||
|
||||
void TradeWindow::setPtr(const MWWorld::Ptr& actor)
|
||||
|
|
@ -203,6 +228,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);
|
||||
|
||||
for (const auto& source : itemSources)
|
||||
source.getClass().getContainerStore(source).setContListener(this);
|
||||
}
|
||||
|
|
@ -353,6 +382,13 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
void TradeWindow::onOfferSubmitted(MyGUI::Widget* _sender, size_t offerAmount)
|
||||
{
|
||||
mCurrentBalance = offerAmount * (mCurrentBalance < 0 ? -1 : 1);
|
||||
updateLabels();
|
||||
onOfferButtonClicked(mOfferButton);
|
||||
}
|
||||
|
||||
void TradeWindow::onOfferButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
TradeItemModel* playerItemModel
|
||||
|
|
@ -658,6 +694,91 @@ namespace MWGui
|
|||
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);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
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);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
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->onControllerButton(arg.button);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TradeWindow::setActiveControllerWindow(bool active)
|
||||
{
|
||||
// Show L1 and R1 buttons next to tabs
|
||||
MyGUI::Widget* image;
|
||||
getWidget(image, "BtnL1Image");
|
||||
image->setVisible(active);
|
||||
|
||||
getWidget(image, "BtnR1Image");
|
||||
image->setVisible(active);
|
||||
|
||||
mItemView->setActiveControllerWindow(active);
|
||||
WindowBase::setActiveControllerWindow(active);
|
||||
}
|
||||
|
||||
void TradeWindow::updateItemView()
|
||||
{
|
||||
mItemView->update();
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ namespace MWGui
|
|||
|
||||
std::string_view getWindowIdForLua() const override { return "Trade"; }
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
void setActiveControllerWindow(bool active) override;
|
||||
|
||||
private:
|
||||
friend class InventoryWindow;
|
||||
|
||||
|
|
@ -113,6 +116,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, size_t offerAmount);
|
||||
|
||||
void addRepeatController(MyGUI::Widget* widget);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,13 @@ namespace MWGui
|
|||
|
||||
mTimeAdvancer.eventProgressChanged += MyGUI::newDelegate(this, &TrainingWindow::onTrainingProgressChanged);
|
||||
mTimeAdvancer.eventFinished += MyGUI::newDelegate(this, &TrainingWindow::onTrainingFinished);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mDisableGamepadCursor = true;
|
||||
mControllerButtons.mA = "#{sBuy}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
}
|
||||
}
|
||||
|
||||
void TrainingWindow::onOpen()
|
||||
|
|
@ -104,6 +111,7 @@ namespace MWGui
|
|||
|
||||
const int lineHeight = Settings::gui().mFontSize + 2;
|
||||
|
||||
mTrainingButtons.clear();
|
||||
for (size_t i = 0; i < skills.size(); ++i)
|
||||
{
|
||||
const ESM::Skill* skill = skills[i].first;
|
||||
|
|
@ -127,6 +135,16 @@ namespace MWGui
|
|||
button->setSize(button->getTextSize().width + 12, button->getSize().height);
|
||||
|
||||
ToolTips::createSkillToolTip(button, skill->mId);
|
||||
|
||||
if (price <= playerGold)
|
||||
mTrainingButtons.emplace_back(button);
|
||||
}
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerFocus = 0;
|
||||
if (mTrainingButtons.size() > 0)
|
||||
mTrainingButtons[0]->setStateSelected(true);
|
||||
}
|
||||
|
||||
center();
|
||||
|
|
@ -228,4 +246,36 @@ namespace MWGui
|
|||
return !mTimeAdvancer.isRunning();
|
||||
}
|
||||
|
||||
bool TrainingWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mControllerFocus < mTrainingButtons.size())
|
||||
onTrainingSelected(mTrainingButtons[mControllerFocus]);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
if (mTrainingButtons.size() <= 1)
|
||||
return true;
|
||||
|
||||
setControllerFocus(mTrainingButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus - 1, mTrainingButtons.size());
|
||||
setControllerFocus(mTrainingButtons, mControllerFocus, true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
if (mTrainingButtons.size() <= 1)
|
||||
return true;
|
||||
|
||||
setControllerFocus(mTrainingButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus + 1, mTrainingButtons.size());
|
||||
setControllerFocus(mTrainingButtons, mControllerFocus, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,9 +49,13 @@ namespace MWGui
|
|||
MyGUI::Widget* mTrainingOptions;
|
||||
MyGUI::Button* mCancelButton;
|
||||
MyGUI::TextBox* mPlayerGold;
|
||||
std::vector<MyGUI::Button*> mTrainingButtons;
|
||||
|
||||
WaitDialogProgressBar mProgressBar;
|
||||
TimeAdvancer mTimeAdvancer;
|
||||
|
||||
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
|
||||
size_t mControllerFocus;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,13 @@ namespace MWGui
|
|||
getWidget(mDestinationsView, "DestinationsView");
|
||||
|
||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TravelWindow::onCancelButtonClicked);
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mDisableGamepadCursor = true;
|
||||
mControllerButtons.mA = "#{sTravel}";
|
||||
mControllerButtons.mB = "#{Interface:Cancel}";
|
||||
}
|
||||
}
|
||||
|
||||
void TravelWindow::addDestination(const ESM::RefId& name, const ESM::Position& pos, bool interior)
|
||||
|
|
@ -94,6 +101,8 @@ namespace MWGui
|
|||
toAdd->setUserString("Destination", nameString);
|
||||
toAdd->setUserData(pos);
|
||||
toAdd->eventMouseButtonClick += MyGUI::newDelegate(this, &TravelWindow::onTravelButtonClick);
|
||||
if (price <= playerGold)
|
||||
mDestinationButtons.emplace_back(toAdd);
|
||||
}
|
||||
|
||||
void TravelWindow::clearDestinations()
|
||||
|
|
@ -102,6 +111,7 @@ namespace MWGui
|
|||
mCurrentY = 0;
|
||||
while (mDestinationsView->getChildCount())
|
||||
MyGUI::Gui::getInstance().destroyWidget(mDestinationsView->getChildAt(0));
|
||||
mDestinationButtons.clear();
|
||||
}
|
||||
|
||||
void TravelWindow::setPtr(const MWWorld::Ptr& actor)
|
||||
|
|
@ -146,6 +156,14 @@ namespace MWGui
|
|||
}
|
||||
|
||||
updateLabels();
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mControllerFocus = 0;
|
||||
if (mDestinationButtons.size() > 0)
|
||||
mDestinationButtons[0]->setStateSelected(true);
|
||||
}
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the
|
||||
// scrollbar is hidden
|
||||
mDestinationsView->setVisibleVScroll(false);
|
||||
|
|
@ -240,4 +258,49 @@ namespace MWGui
|
|||
mDestinationsView->setViewOffset(
|
||||
MyGUI::IntPoint(0, static_cast<int>(mDestinationsView->getViewOffset().top + _rel * 0.3f)));
|
||||
}
|
||||
|
||||
bool TravelWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
{
|
||||
if (arg.button == SDL_CONTROLLER_BUTTON_A)
|
||||
{
|
||||
if (mControllerFocus < mDestinationButtons.size())
|
||||
{
|
||||
onTravelButtonClick(mDestinationButtons[mControllerFocus]);
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click"));
|
||||
}
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
|
||||
{
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
{
|
||||
if (mDestinationButtons.size() <= 1)
|
||||
return true;
|
||||
|
||||
setControllerFocus(mDestinationButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus - 1, mDestinationButtons.size());
|
||||
setControllerFocus(mDestinationButtons, mControllerFocus, true);
|
||||
}
|
||||
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
{
|
||||
if (mDestinationButtons.size() <= 1)
|
||||
return true;
|
||||
|
||||
setControllerFocus(mDestinationButtons, mControllerFocus, false);
|
||||
mControllerFocus = wrap(mControllerFocus + 1, mDestinationButtons.size());
|
||||
setControllerFocus(mDestinationButtons, mControllerFocus, true);
|
||||
}
|
||||
|
||||
// Scroll the list to keep the active item in view
|
||||
if (mControllerFocus <= 5)
|
||||
mDestinationsView->setViewOffset(MyGUI::IntPoint(0, 0));
|
||||
else
|
||||
{
|
||||
const int lineHeight = Settings::gui().mFontSize + 2;
|
||||
mDestinationsView->setViewOffset(MyGUI::IntPoint(0, -lineHeight * (mControllerFocus - 5)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue