Fixed multiple navigation issues.

This commit is contained in:
Leon Styhre 2022-12-04 15:56:59 +01:00
parent 4b03c90bf3
commit da93533aed
3 changed files with 95 additions and 63 deletions

View file

@ -205,6 +205,9 @@ std::vector<HelpPrompt> SystemView::getHelpPrompts()
else else
prompts.push_back(HelpPrompt("left/right", "choose")); prompts.push_back(HelpPrompt("left/right", "choose"));
} }
else if (mGrid != nullptr) {
prompts.push_back(HelpPrompt("up/down/left/right", "choose"));
}
else if (mTextList != nullptr) { else if (mTextList != nullptr) {
prompts.push_back(HelpPrompt("up/down", "choose")); prompts.push_back(HelpPrompt("up/down", "choose"));
} }
@ -223,9 +226,43 @@ std::vector<HelpPrompt> SystemView::getHelpPrompts()
void SystemView::onCursorChanged(const CursorState& state) void SystemView::onCursorChanged(const CursorState& state)
{ {
const int cursor {mPrimary->getCursor()}; const int cursor {mPrimary->getCursor()};
const int scrollVelocity {mPrimary->getScrollingVelocity()};
const std::string& transitionStyle {Settings::getInstance()->getString("TransitionStyle")}; const std::string& transitionStyle {Settings::getInstance()->getString("TransitionStyle")};
mFadeTransitions = transitionStyle == "fade"; mFadeTransitions = transitionStyle == "fade";
// Some logic needed to avoid various navigation glitches with GridComponent and
// TextListComponent.
if (state == CursorState::CURSOR_STOPPED && mCarousel == nullptr) {
const int numEntries {static_cast<int>(mPrimary->getNumEntries())};
bool doStop {false};
if (cursor == 0 && mLastCursor == numEntries - 1 && std::abs(scrollVelocity) == 1)
doStop = false;
else if (cursor == 0)
doStop = true;
else if (cursor == numEntries - 1 && mLastCursor == 0 && std::abs(scrollVelocity) == 1)
doStop = false;
else if (cursor == numEntries - 1)
doStop = true;
if (!doStop && mGrid != nullptr && std::abs(scrollVelocity) == mGrid->getColumnCount()) {
const int columns {mGrid->getColumnCount()};
const int columnModulus {numEntries % columns};
if (cursor < columns)
doStop = true;
else if (cursor >= numEntries - (columnModulus == 0 ? columns : columnModulus))
doStop = true;
}
if (doStop) {
if (mGrid != nullptr)
mGrid->setScrollVelocity(0);
mPrimary->stopScrolling();
mNavigated = false;
}
}
// Avoid double updates. // Avoid double updates.
if (cursor != mLastCursor) { if (cursor != mLastCursor) {
for (auto& selector : mSystemElements[cursor].gameSelectors) { for (auto& selector : mSystemElements[cursor].gameSelectors) {
@ -239,8 +276,6 @@ void SystemView::onCursorChanged(const CursorState& state)
video->stopVideoPlayer(); video->stopVideoPlayer();
} }
const int scrollVelocity {mPrimary->getScrollingVelocity()};
// This is needed to avoid erratic camera movements during extreme navigation input when using // This is needed to avoid erratic camera movements during extreme navigation input when using
// slide transitions. This should very rarely occur during normal application usage. // slide transitions. This should very rarely occur during normal application usage.
if (transitionStyle == "slide") { if (transitionStyle == "slide") {

View file

@ -41,6 +41,9 @@ public:
void updateEntry(Entry& entry, const std::shared_ptr<ThemeData>& theme); void updateEntry(Entry& entry, const std::shared_ptr<ThemeData>& theme);
void onDemandTextureLoad() override; void onDemandTextureLoad() override;
void calculateLayout(); void calculateLayout();
const int getColumnCount() const { return mColumns; }
const int getRowCount() const { return mRows; }
void setScrollVelocity(int velocity) { mScrollVelocity = velocity; }
void setCancelTransitionsCallback(const std::function<void()>& func) override void setCancelTransitionsCallback(const std::function<void()>& func) override
{ {
@ -93,7 +96,11 @@ private:
const T& getPrevious() const override { return List::getPrevious(); } const T& getPrevious() const override { return List::getPrevious(); }
const T& getFirst() const override { return List::getFirst(); } const T& getFirst() const override { return List::getFirst(); }
const T& getLast() const override { return List::getLast(); } const T& getLast() const override { return List::getLast(); }
bool setCursor(const T& obj) override { return List::setCursor(obj); } bool setCursor(const T& obj) override
{
mLastCursor = mCursor;
return List::setCursor(obj);
}
bool remove(const T& obj) override { return List::remove(obj); } bool remove(const T& obj) override { return List::remove(obj); }
int size() const override { return List::size(); } int size() const override { return List::size(); }
@ -129,7 +136,6 @@ private:
bool mGamelistView; bool mGamelistView;
bool mFractionalRows; bool mFractionalRows;
bool mLayoutValid; bool mLayoutValid;
bool mRowJump;
bool mWasScrolling; bool mWasScrolling;
bool mJustCalculatedLayout; bool mJustCalculatedLayout;
}; };
@ -164,7 +170,6 @@ GridComponent<T>::GridComponent()
, mGamelistView {std::is_same_v<T, FileData*> ? true : false} , mGamelistView {std::is_same_v<T, FileData*> ? true : false}
, mFractionalRows {false} , mFractionalRows {false}
, mLayoutValid {false} , mLayoutValid {false}
, mRowJump {false}
, mWasScrolling {false} , mWasScrolling {false}
, mJustCalculatedLayout {false} , mJustCalculatedLayout {false}
{ {
@ -377,36 +382,33 @@ template <typename T> bool GridComponent<T>::input(InputConfig* config, Input in
{ {
if (size() > 0) { if (size() > 0) {
if (input.value != 0) { if (input.value != 0) {
mRowJump = false;
if (config->isMappedLike("left", input)) { if (config->isMappedLike("left", input)) {
if (mCancelTransitionsCallback) if (mCancelTransitionsCallback)
mCancelTransitionsCallback(); mCancelTransitionsCallback();
if (mCursor % mColumns == 0)
mRowJump = true;
List::listInput(-1); List::listInput(-1);
return true; return true;
} }
if (config->isMappedLike("right", input)) { if (config->isMappedLike("right", input)) {
if (mCancelTransitionsCallback) if (mCancelTransitionsCallback)
mCancelTransitionsCallback(); mCancelTransitionsCallback();
if (mCursor % mColumns == mColumns - 1)
mRowJump = true;
List::listInput(1); List::listInput(1);
return true; return true;
} }
if (config->isMappedLike("up", input)) { if (config->isMappedLike("up", input)) {
if (mCursor >= mColumns) {
if (mCancelTransitionsCallback) if (mCancelTransitionsCallback)
mCancelTransitionsCallback(); mCancelTransitionsCallback();
mRowJump = true;
List::listInput(-mColumns); List::listInput(-mColumns);
}
return true; return true;
} }
if (config->isMappedLike("down", input)) { if (config->isMappedLike("down", input)) {
const int columnModulus {size() % mColumns};
if (mCursor < size() - (columnModulus == 0 ? mColumns : columnModulus)) {
if (mCancelTransitionsCallback) if (mCancelTransitionsCallback)
mCancelTransitionsCallback(); mCancelTransitionsCallback();
mRowJump = true;
List::listInput(mColumns); List::listInput(mColumns);
}
return true; return true;
} }
if (config->isMappedLike("lefttrigger", input)) { if (config->isMappedLike("lefttrigger", input)) {
@ -732,7 +734,6 @@ template <typename T> void GridComponent<T>::onCursorChanged(const CursorState&
else else
endRow -= visibleRows; endRow -= visibleRows;
if (startPos != endPos) {
Animation* anim {new LambdaAnimation( Animation* anim {new LambdaAnimation(
[this, startPos, endPos, posMax, startRow, endRow](float t) { [this, startPos, endPos, posMax, startRow, endRow](float t) {
// Non-linear interpolation. // Non-linear interpolation.
@ -764,7 +765,6 @@ template <typename T> void GridComponent<T>::onCursorChanged(const CursorState&
static_cast<int>(animTime))}; static_cast<int>(animTime))};
GuiComponent::setAnimation(anim, 0, nullptr, false, 0); GuiComponent::setAnimation(anim, 0, nullptr, false, 0);
}
if (mCursorChangedCallback) if (mCursorChangedCallback)
mCursorChangedCallback(state); mCursorChangedCallback(state);

View file

@ -201,15 +201,19 @@ template <typename T> bool TextListComponent<T>::input(InputConfig* config, Inpu
return true; return true;
} }
if (config->isMappedLike("leftshoulder", input)) { if (config->isMappedLike("leftshoulder", input)) {
if (mCursor != 0) {
if (mCancelTransitionsCallback) if (mCancelTransitionsCallback)
mCancelTransitionsCallback(); mCancelTransitionsCallback();
List::listInput(-10); List::listInput(-10);
}
return true; return true;
} }
if (config->isMappedLike("rightshoulder", input)) { if (config->isMappedLike("rightshoulder", input)) {
if (mCursor != size() - 1) {
if (mCancelTransitionsCallback) if (mCancelTransitionsCallback)
mCancelTransitionsCallback(); mCancelTransitionsCallback();
List::listInput(10); List::listInput(10);
}
return true; return true;
} }
if (config->isMappedLike("lefttrigger", input)) { if (config->isMappedLike("lefttrigger", input)) {
@ -233,17 +237,10 @@ template <typename T> bool TextListComponent<T>::input(InputConfig* config, Inpu
config->isMappedLike("rightshoulder", input) || config->isMappedLike("rightshoulder", input) ||
config->isMappedLike("lefttrigger", input) || config->isMappedLike("lefttrigger", input) ||
config->isMappedLike("righttrigger", input)) { config->isMappedLike("righttrigger", input)) {
if constexpr (std::is_same_v<T, SystemData*>) {
if (isScrolling()) if (isScrolling())
onCursorChanged(CursorState::CURSOR_STOPPED); onCursorChanged(CursorState::CURSOR_STOPPED);
List::listInput(0); List::listInput(0);
} }
else {
if (isScrolling())
onCursorChanged(CursorState::CURSOR_STOPPED);
List::listInput(0);
}
}
} }
} }