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
prompts.push_back(HelpPrompt("left/right", "choose"));
}
else if (mGrid != nullptr) {
prompts.push_back(HelpPrompt("up/down/left/right", "choose"));
}
else if (mTextList != nullptr) {
prompts.push_back(HelpPrompt("up/down", "choose"));
}
@ -223,9 +226,43 @@ std::vector<HelpPrompt> SystemView::getHelpPrompts()
void SystemView::onCursorChanged(const CursorState& state)
{
const int cursor {mPrimary->getCursor()};
const int scrollVelocity {mPrimary->getScrollingVelocity()};
const std::string& transitionStyle {Settings::getInstance()->getString("TransitionStyle")};
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.
if (cursor != mLastCursor) {
for (auto& selector : mSystemElements[cursor].gameSelectors) {
@ -239,8 +276,6 @@ void SystemView::onCursorChanged(const CursorState& state)
video->stopVideoPlayer();
}
const int scrollVelocity {mPrimary->getScrollingVelocity()};
// 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.
if (transitionStyle == "slide") {

View file

@ -41,6 +41,9 @@ public:
void updateEntry(Entry& entry, const std::shared_ptr<ThemeData>& theme);
void onDemandTextureLoad() override;
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
{
@ -93,7 +96,11 @@ private:
const T& getPrevious() const override { return List::getPrevious(); }
const T& getFirst() const override { return List::getFirst(); }
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); }
int size() const override { return List::size(); }
@ -129,7 +136,6 @@ private:
bool mGamelistView;
bool mFractionalRows;
bool mLayoutValid;
bool mRowJump;
bool mWasScrolling;
bool mJustCalculatedLayout;
};
@ -164,7 +170,6 @@ GridComponent<T>::GridComponent()
, mGamelistView {std::is_same_v<T, FileData*> ? true : false}
, mFractionalRows {false}
, mLayoutValid {false}
, mRowJump {false}
, mWasScrolling {false}
, mJustCalculatedLayout {false}
{
@ -377,36 +382,33 @@ template <typename T> bool GridComponent<T>::input(InputConfig* config, Input in
{
if (size() > 0) {
if (input.value != 0) {
mRowJump = false;
if (config->isMappedLike("left", input)) {
if (mCancelTransitionsCallback)
mCancelTransitionsCallback();
if (mCursor % mColumns == 0)
mRowJump = true;
List::listInput(-1);
return true;
}
if (config->isMappedLike("right", input)) {
if (mCancelTransitionsCallback)
mCancelTransitionsCallback();
if (mCursor % mColumns == mColumns - 1)
mRowJump = true;
List::listInput(1);
return true;
}
if (config->isMappedLike("up", input)) {
if (mCancelTransitionsCallback)
mCancelTransitionsCallback();
mRowJump = true;
List::listInput(-mColumns);
if (mCursor >= mColumns) {
if (mCancelTransitionsCallback)
mCancelTransitionsCallback();
List::listInput(-mColumns);
}
return true;
}
if (config->isMappedLike("down", input)) {
if (mCancelTransitionsCallback)
mCancelTransitionsCallback();
mRowJump = true;
List::listInput(mColumns);
const int columnModulus {size() % mColumns};
if (mCursor < size() - (columnModulus == 0 ? mColumns : columnModulus)) {
if (mCancelTransitionsCallback)
mCancelTransitionsCallback();
List::listInput(mColumns);
}
return true;
}
if (config->isMappedLike("lefttrigger", input)) {
@ -732,39 +734,37 @@ template <typename T> void GridComponent<T>::onCursorChanged(const CursorState&
else
endRow -= visibleRows;
if (startPos != endPos) {
Animation* anim {new LambdaAnimation(
[this, startPos, endPos, posMax, startRow, endRow](float t) {
// Non-linear interpolation.
t = 1.0f - (1.0f - t) * (1.0f - t);
Animation* anim {new LambdaAnimation(
[this, startPos, endPos, posMax, startRow, endRow](float t) {
// Non-linear interpolation.
t = 1.0f - (1.0f - t) * (1.0f - t);
float f {(endPos * t) + (startPos * (1.0f - t))};
if (f < 0)
f += posMax;
if (f >= posMax)
f -= posMax;
float f {(endPos * t) + (startPos * (1.0f - t))};
if (f < 0)
f += posMax;
if (f >= posMax)
f -= posMax;
mEntryOffset = f;
mEntryOffset = f;
if (mInstantRowTransitions)
mScrollPos = endRow;
else
mScrollPos = {(endRow * t) + (startRow * (1.0f - t))};
if (mInstantRowTransitions)
mScrollPos = endRow;
else
mScrollPos = {(endRow * t) + (startRow * (1.0f - t))};
if (mInstantItemTransitions) {
mTransitionFactor = 1.0f;
}
else {
// Linear interpolation.
mTransitionFactor = t;
// Non-linear interpolation doesn't seem to be a good match for this component.
// mTransitionFactor = {(1.0f * t) + (0.0f * (1.0f - t))};
}
},
static_cast<int>(animTime))};
if (mInstantItemTransitions) {
mTransitionFactor = 1.0f;
}
else {
// Linear interpolation.
mTransitionFactor = t;
// Non-linear interpolation doesn't seem to be a good match for this component.
// mTransitionFactor = {(1.0f * t) + (0.0f * (1.0f - t))};
}
},
static_cast<int>(animTime))};
GuiComponent::setAnimation(anim, 0, nullptr, false, 0);
}
GuiComponent::setAnimation(anim, 0, nullptr, false, 0);
if (mCursorChangedCallback)
mCursorChangedCallback(state);

View file

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