mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 14:15:38 +00:00
Added support for correctly navigating arbitrarily sized ComponentGrid entries.
Also added a callback for handling navigation attempts beyond the grid boundary as well as a function to move to an absolute cursor position.
This commit is contained in:
parent
db4fb1ab92
commit
08790ed1f3
|
@ -252,19 +252,24 @@ bool ComponentGrid::input(InputConfig* config, Input input)
|
|||
if (!input.value)
|
||||
return false;
|
||||
|
||||
bool withinBoundary = false;
|
||||
|
||||
if (config->isMappedLike("down", input))
|
||||
return moveCursor(glm::ivec2{0, 1});
|
||||
withinBoundary = moveCursor(glm::ivec2{0, 1});
|
||||
|
||||
if (config->isMappedLike("up", input))
|
||||
return moveCursor(glm::ivec2{0, -1});
|
||||
withinBoundary = moveCursor(glm::ivec2{0, -1});
|
||||
|
||||
if (config->isMappedLike("left", input))
|
||||
return moveCursor(glm::ivec2{-1, 0});
|
||||
withinBoundary = moveCursor(glm::ivec2{-1, 0});
|
||||
|
||||
if (config->isMappedLike("right", input))
|
||||
return moveCursor(glm::ivec2{1, 0});
|
||||
withinBoundary = moveCursor(glm::ivec2{1, 0});
|
||||
|
||||
return false;
|
||||
if (!withinBoundary && mPastBoundaryCallback)
|
||||
return mPastBoundaryCallback(config, input);
|
||||
|
||||
return withinBoundary;
|
||||
}
|
||||
|
||||
void ComponentGrid::resetCursor()
|
||||
|
@ -290,6 +295,34 @@ bool ComponentGrid::moveCursor(glm::ivec2 dir)
|
|||
const GridEntry* currentCursorEntry = getCellAt(mCursor);
|
||||
glm::ivec2 searchAxis(dir.x == 0, dir.y == 0);
|
||||
|
||||
// Logic to handle entries that span several cells.
|
||||
if (currentCursorEntry->dim.x > 1) {
|
||||
if (dir.x < 0 && currentCursorEntry->pos.x == 0 && mCursor.x > currentCursorEntry->pos.x) {
|
||||
onCursorMoved(mCursor, glm::ivec2{0, mCursor.y});
|
||||
mCursor.x = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dir.x > 0 && currentCursorEntry->pos.x + currentCursorEntry->dim.x == mGridSize.x &&
|
||||
mCursor.x < currentCursorEntry->pos.x + currentCursorEntry->dim.x - 1) {
|
||||
onCursorMoved(mCursor, glm::ivec2{mGridSize.x - 1, mCursor.y});
|
||||
mCursor.x = mGridSize.x - 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dir.x > 0 && mCursor.x != currentCursorEntry->pos.x + currentCursorEntry->dim.x - 1)
|
||||
dir.x = currentCursorEntry->dim.x - (mCursor.x - currentCursorEntry->pos.x);
|
||||
else if (dir.x < 0 && mCursor.x != currentCursorEntry->pos.x)
|
||||
dir.x = -(mCursor.x - currentCursorEntry->pos.x + 1);
|
||||
}
|
||||
|
||||
if (currentCursorEntry->dim.y > 1) {
|
||||
if (dir.y > 0 && mCursor.y != currentCursorEntry->pos.y + currentCursorEntry->dim.y - 1)
|
||||
dir.y = currentCursorEntry->dim.y - (mCursor.y - currentCursorEntry->pos.y);
|
||||
else if (dir.y < 0 && mCursor.y != currentCursorEntry->pos.y)
|
||||
dir.y = -(mCursor.y - currentCursorEntry->pos.y + 1);
|
||||
}
|
||||
|
||||
while (mCursor.x >= 0 && mCursor.y >= 0 && mCursor.x < mGridSize.x && mCursor.y < mGridSize.y) {
|
||||
mCursor = mCursor + dir;
|
||||
glm::ivec2 curDirPos{mCursor};
|
||||
|
@ -299,6 +332,13 @@ bool ComponentGrid::moveCursor(glm::ivec2 dir)
|
|||
while (mCursor.x < mGridSize.x && mCursor.y < mGridSize.y && mCursor.x >= 0 &&
|
||||
mCursor.y >= 0) {
|
||||
cursorEntry = getCellAt(mCursor);
|
||||
|
||||
// Multi-cell entries.
|
||||
if (dir.x < 0 && cursorEntry->dim.x > 1)
|
||||
mCursor.x = getCellAt(origCursor)->pos.x - cursorEntry->dim.x;
|
||||
if (dir.y < 0 && cursorEntry->dim.y > 1)
|
||||
mCursor.y = getCellAt(origCursor)->pos.y - cursorEntry->dim.y;
|
||||
|
||||
if (cursorEntry && cursorEntry->canFocus && cursorEntry != currentCursorEntry) {
|
||||
onCursorMoved(origCursor, mCursor);
|
||||
return true;
|
||||
|
@ -326,6 +366,24 @@ bool ComponentGrid::moveCursor(glm::ivec2 dir)
|
|||
return false;
|
||||
}
|
||||
|
||||
void ComponentGrid::moveCursorTo(int xPos, int yPos, bool selectLeftCell)
|
||||
{
|
||||
const glm::ivec2 origCursor{mCursor};
|
||||
|
||||
if (xPos != -1)
|
||||
mCursor.x = xPos;
|
||||
if (yPos != -1)
|
||||
mCursor.y = yPos;
|
||||
|
||||
const GridEntry* currentCursorEntry = getCellAt(mCursor);
|
||||
|
||||
// If requested, select the leftmost cell of entries wider than 1 cell.
|
||||
if (selectLeftCell && mCursor.x > currentCursorEntry->pos.x)
|
||||
mCursor.x = currentCursorEntry->pos.x;
|
||||
|
||||
onCursorMoved(origCursor, mCursor);
|
||||
}
|
||||
|
||||
void ComponentGrid::onFocusLost()
|
||||
{
|
||||
const GridEntry* cursorEntry = getCellAt(mCursor);
|
||||
|
|
|
@ -46,6 +46,11 @@ public:
|
|||
unsigned int border = GridFlags::BORDER_NONE,
|
||||
GridFlags::UpdateType updateType = GridFlags::UPDATE_ALWAYS);
|
||||
|
||||
void setPastBoundaryCallback(const std::function<bool(InputConfig* config, Input input)>& func)
|
||||
{
|
||||
mPastBoundaryCallback = func;
|
||||
}
|
||||
|
||||
void textInput(const std::string& text) override;
|
||||
bool input(InputConfig* config, Input input) override;
|
||||
void update(int deltaTime) override;
|
||||
|
@ -65,6 +70,8 @@ public:
|
|||
void setRowHeightPerc(int row, float height, bool update = true);
|
||||
|
||||
bool moveCursor(glm::ivec2 dir);
|
||||
// Pass -1 for xPos or yPos to keep its axis cursor position.
|
||||
void moveCursorTo(int xPos, int yPos, bool selectLeftCell = false);
|
||||
void setCursorTo(const std::shared_ptr<GuiComponent>& comp);
|
||||
|
||||
std::shared_ptr<GuiComponent> getSelectedComponent()
|
||||
|
@ -126,6 +133,8 @@ private:
|
|||
std::vector<GridEntry> mCells;
|
||||
glm::ivec2 mCursor;
|
||||
|
||||
std::function<bool(InputConfig* config, Input input)> mPastBoundaryCallback;
|
||||
|
||||
float* mRowHeights;
|
||||
float* mColWidths;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue