mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-03-06 14:27:43 +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
es-core/src/components
|
@ -252,19 +252,24 @@ bool ComponentGrid::input(InputConfig* config, Input input)
|
||||||
if (!input.value)
|
if (!input.value)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
bool withinBoundary = false;
|
||||||
|
|
||||||
if (config->isMappedLike("down", input))
|
if (config->isMappedLike("down", input))
|
||||||
return moveCursor(glm::ivec2{0, 1});
|
withinBoundary = moveCursor(glm::ivec2{0, 1});
|
||||||
|
|
||||||
if (config->isMappedLike("up", input))
|
if (config->isMappedLike("up", input))
|
||||||
return moveCursor(glm::ivec2{0, -1});
|
withinBoundary = moveCursor(glm::ivec2{0, -1});
|
||||||
|
|
||||||
if (config->isMappedLike("left", input))
|
if (config->isMappedLike("left", input))
|
||||||
return moveCursor(glm::ivec2{-1, 0});
|
withinBoundary = moveCursor(glm::ivec2{-1, 0});
|
||||||
|
|
||||||
if (config->isMappedLike("right", input))
|
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()
|
void ComponentGrid::resetCursor()
|
||||||
|
@ -290,6 +295,34 @@ bool ComponentGrid::moveCursor(glm::ivec2 dir)
|
||||||
const GridEntry* currentCursorEntry = getCellAt(mCursor);
|
const GridEntry* currentCursorEntry = getCellAt(mCursor);
|
||||||
glm::ivec2 searchAxis(dir.x == 0, dir.y == 0);
|
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) {
|
while (mCursor.x >= 0 && mCursor.y >= 0 && mCursor.x < mGridSize.x && mCursor.y < mGridSize.y) {
|
||||||
mCursor = mCursor + dir;
|
mCursor = mCursor + dir;
|
||||||
glm::ivec2 curDirPos{mCursor};
|
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 &&
|
while (mCursor.x < mGridSize.x && mCursor.y < mGridSize.y && mCursor.x >= 0 &&
|
||||||
mCursor.y >= 0) {
|
mCursor.y >= 0) {
|
||||||
cursorEntry = getCellAt(mCursor);
|
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) {
|
if (cursorEntry && cursorEntry->canFocus && cursorEntry != currentCursorEntry) {
|
||||||
onCursorMoved(origCursor, mCursor);
|
onCursorMoved(origCursor, mCursor);
|
||||||
return true;
|
return true;
|
||||||
|
@ -326,6 +366,24 @@ bool ComponentGrid::moveCursor(glm::ivec2 dir)
|
||||||
return false;
|
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()
|
void ComponentGrid::onFocusLost()
|
||||||
{
|
{
|
||||||
const GridEntry* cursorEntry = getCellAt(mCursor);
|
const GridEntry* cursorEntry = getCellAt(mCursor);
|
||||||
|
|
|
@ -46,6 +46,11 @@ public:
|
||||||
unsigned int border = GridFlags::BORDER_NONE,
|
unsigned int border = GridFlags::BORDER_NONE,
|
||||||
GridFlags::UpdateType updateType = GridFlags::UPDATE_ALWAYS);
|
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;
|
void textInput(const std::string& text) override;
|
||||||
bool input(InputConfig* config, Input input) override;
|
bool input(InputConfig* config, Input input) override;
|
||||||
void update(int deltaTime) override;
|
void update(int deltaTime) override;
|
||||||
|
@ -65,6 +70,8 @@ public:
|
||||||
void setRowHeightPerc(int row, float height, bool update = true);
|
void setRowHeightPerc(int row, float height, bool update = true);
|
||||||
|
|
||||||
bool moveCursor(glm::ivec2 dir);
|
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);
|
void setCursorTo(const std::shared_ptr<GuiComponent>& comp);
|
||||||
|
|
||||||
std::shared_ptr<GuiComponent> getSelectedComponent()
|
std::shared_ptr<GuiComponent> getSelectedComponent()
|
||||||
|
@ -126,6 +133,8 @@ private:
|
||||||
std::vector<GridEntry> mCells;
|
std::vector<GridEntry> mCells;
|
||||||
glm::ivec2 mCursor;
|
glm::ivec2 mCursor;
|
||||||
|
|
||||||
|
std::function<bool(InputConfig* config, Input input)> mPastBoundaryCallback;
|
||||||
|
|
||||||
float* mRowHeights;
|
float* mRowHeights;
|
||||||
float* mColWidths;
|
float* mColWidths;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue