Replies: 2 comments 6 replies
-
Hey, this feature is very new, so it's cool to hear feedback. You could also take a look at some of the design decisions in the pull request for this feature. Let me know if you have some suggestions, I'm sure we can improve this. To answer your specific questions.
|
Beta Was this translation helpful? Give feedback.
-
I found a simple case where auto-nav breaks down @mikke89 - this is a drop-in for demo.rml: <rml>
<head>
<title>Demo</title>
<link type="text/template" href="window.rml" />
<style>
body
{
width: 300dp;
height: 225dp;
margin: auto;
}
div#title_bar div#icon
{
display: none;
}
div#content
{
text-align: left;
}
div.grid
{
display: block;
width: 90dp;
height: 90dp;
line-height: 0;
}
div.grid > div
{
display: inline-block;
box-sizing: border-box;
border: 1px red;
width: 30dp;
height: 30dp;
focus: auto;
nav: auto;
tab-index: auto;
}
div.grid > div:focus
{
border: 1px blue;
}
div.grid > div:active
{
border: 1px green;
}
</style>
</head>
<body template="window">
<div class="grid">
<div />
<div />
<div />
<div />
<div />
<div />
<div />
<div />
<div />
</div>
</body>
</rml> For a "key pad" grid like this, the auto-spatial nav heuristic is preferring cross-axis navigation instead of axial. Visually looking at the I came up with this as a quick solution: int GetNavigationHeuristic(const BoundingBox& source, const BoundingBox& target, NavigationSearchDirection direction)
{
enum Axis { Horizontal = 0, Vertical = 1 };
auto CalculateHeuristic = [](Axis axis, const BoundingBox& a, const BoundingBox& b, const Vector2f& dir_axis) -> int {
// The heuristic is mainly the distance from the source to the target along the specified direction. In
// addition, the following factor determines the penalty for being outside the projected area of the element in
// the given direction, as a multiplier of the cross-axis distance between the target and projected area.
static constexpr int CrossAxisFactor = 10'000;
const int main_axis = int(a.min[axis] - b.max[axis]);
if (main_axis < 0)
return Infinite;
auto a_centroid = (a.min + a.max) * 0.5f;
auto b_centroid = (b.min + b.max) * 0.5f;
const Axis cross = Axis((axis + 1) % 2);
const int cross_axis = Math::Max(0, int(b_centroid[cross] - a_centroid[cross])) + Math::Max(0, int(a_centroid[cross] - b_centroid[cross]));
// Prefer elements that are touching; these always get the lowest heuristics
// regardless of distances.
static constexpr int TouchingFactor = 10'000;
if (main_axis == 0 && cross_axis == 0)
{
auto ab_axis = (a_centroid - b_centroid).Normalise();
auto dot = 1.0f - fabsf(dir_axis.DotProduct(ab_axis));
return (int) abs(dot * TouchingFactor);
}
return TouchingFactor + (main_axis + CrossAxisFactor * cross_axis);
};
switch (direction)
{
case NavigationSearchDirection::Up: return CalculateHeuristic(Vertical, source, target, { 0.0f, -1.0f });
case NavigationSearchDirection::Down: return CalculateHeuristic(Vertical, target, source, { 0.0f, 1.0f });
case NavigationSearchDirection::Right: return CalculateHeuristic(Horizontal, target, source, { 1.0f, 0.0f });
case NavigationSearchDirection::Left: return CalculateHeuristic(Horizontal, source, target, { -1.0f, 0.0f });
}
RMLUI_ERROR;
return Infinite;
} This seems to work in my limited testing. I can file a PR for it soon (after cleaning it up a bit) and will play with it locally before I do so. EDIT 2: updated code above; the min/max for cross axis appears to be incorrect, it seems to cause it to prefer elements to the side rather than straight. Using the centroid seems to work better. |
Beta Was this translation helpful? Give feedback.
-
I'm using a fairly basic setup where I have a list of menu options, and inside the focusable item there may be a controllable object that should be modified when the parent is selected - essentially the parent element should be highlighted with focus, but the underlying input is what's actually being modified, if that makes sense. Here's a very rough example of the kind of setup I'm using currently:
I've been running into a few issues, though, and I'm wondering if I'm maybe doing something wrong here;
.item
it seems to be OK, but that doesn't allow pass-through to work properly for enter/space and left/right arrows:focus
selector seems to propagate upwards to the .item, which isn't mentioned in the documentation and seems to have non-standard behavior; is it intentional that it acts more like:focus-within
than:focus
in regular CSS?nav
CSS property refer to a DOM id is very odd - wouldn't this be more appropriate as a DOM attribute? it makes setting up custom navigation graphs difficult since we have to make a single style per itemBeta Was this translation helpful? Give feedback.
All reactions