/// <summary>
/// Update the navigation.
/// </summary>
protected virtual void UpdateNavigation()
{
if (m_NavigationType == ItemShapeNavigation.Custom) {
return;
}
if (m_NavigationType == ItemShapeNavigation.PerSlot) {
SetGridLayoutGroupNavigation(m_GridLayoutGroup, false);
return;
}
if (m_NavigationType == ItemShapeNavigation.PerItem) {
SetNavigationPerItem(m_GridLayoutGroup);
return;
}
}
/// <summary>
/// Set the grid layout group navigation.
/// </summary>
/// <param name="gridLayoutGroup">The grid layout group.</param>
/// <param name="gridWrap">Should the navigation wrap around?</param>
public void SetNavigationPerItem(GridLayoutGroup gridLayoutGroup)
{
Vector2Int gridSize = Vector2Int.zero;
if (gridLayoutGroup.constraint == GridLayoutGroup.Constraint.Flexible) {
return;
}
var gridParent = gridLayoutGroup.transform;
if (gridLayoutGroup.constraint == GridLayoutGroup.Constraint.FixedColumnCount) {
gridSize = new Vector2Int(gridLayoutGroup.constraintCount,
gridParent.childCount / gridLayoutGroup.constraintCount);
}
if (gridLayoutGroup.constraint == GridLayoutGroup.Constraint.FixedRowCount) {
gridSize = new Vector2Int(gridParent.childCount / gridLayoutGroup.constraintCount,
gridLayoutGroup.constraintCount);
}
var horizontalStartAxis = gridLayoutGroup.startAxis == GridLayoutGroup.Axis.Horizontal;
// Go through all the anchors first
for (int i = 0; i < gridSize.y; i++) {
for (int j = 0; j < gridSize.x; j++) {
var index = horizontalStartAxis ?
i * gridSize.x + j :
j * gridSize.y + i;
var currentItemViewSlot = m_ItemViewSlots[index];
if (IsSlotAnchor(currentItemViewSlot) == false) { continue; }
var navigation = currentItemViewSlot.navigation;
navigation.mode = Navigation.Mode.Explicit;
navigation.selectOnUp = GetAnchorSlotInDirection(Vector2Int.up, j, i, horizontalStartAxis, gridSize, currentItemViewSlot);
navigation.selectOnDown = GetAnchorSlotInDirection(Vector2Int.down, j, i, horizontalStartAxis, gridSize, currentItemViewSlot);
navigation.selectOnLeft = GetAnchorSlotInDirection(Vector2Int.left, j, i, horizontalStartAxis, gridSize, currentItemViewSlot);
navigation.selectOnRight = GetAnchorSlotInDirection(Vector2Int.right, j, i, horizontalStartAxis, gridSize, currentItemViewSlot);
currentItemViewSlot.navigation = navigation;
}
}
// Go through all the non-anchors and copy the anchors navigation
for (int i = 0; i < gridSize.y; i++) {
for (int j = 0; j < gridSize.x; j++) {
var index = horizontalStartAxis ?
i * gridSize.x + j :
j * gridSize.y + i;
var currentItemViewSlot = m_ItemViewSlots[index];
var itemShapeView = currentItemViewSlot.ItemView.gameObject.GetCachedComponent<ItemShapeItemView>();
if (itemShapeView.IsAnchor) { continue; }
var anchorIndex = itemShapeView.AnchorIndex;
if (anchorIndex < 0 || anchorIndex >= m_ItemViewSlots.Length) {
continue;
}
var anchorItemViewSlot = m_ItemViewSlots[anchorIndex];
currentItemViewSlot.navigation = anchorItemViewSlot.navigation;
}
}
}
protected static bool IsSlotAnchor(ItemViewSlot currentItemViewSlot)
{
var itemShapeView = currentItemViewSlot.ItemView.gameObject.GetCachedComponent<ItemShapeItemView>();
return itemShapeView.IsAnchor;
}
/// <summary>
/// Get the Anchor slot above the specified position.
/// </summary>
/// <param name="direction">The direction in which to search</param>
/// <param name="x">The x position.</param>
/// <param name="y">The y position.</param>
/// <param name="startHorizontal">Does the grid start in horizontal axis?</param>
/// <param name="gridSize">The grid size.</param>
/// <param name="exception">Ingore that item view slot.</param>
/// <returns>The anchor Item View Slot above the current position.</returns>
private ItemViewSlot GetAnchorSlotInDirection(Vector2Int direction, int x, int y, bool startHorizontal, Vector2Int gridSize, ItemViewSlot exception)
{
if (direction == Vector2Int.zero) {
Debug.LogWarning("Searching in not direction is not allowed");
return null;
}
while ( y >= 0 && y < gridSize.y && x >= 0 && x < gridSize.x) {
var index = startHorizontal?
y * gridSize.x + x:
x * gridSize.y + y;
if (index < 0 || index >= m_ItemViewSlots.Length) {
continue;
}
if (TryGetAnchorItemViewSlot(index, out var viewSlot) && viewSlot != exception) {
return viewSlot;
}
if (startHorizontal) {
x += direction.x;
y -= direction.y;
} else {
x += direction.x;
y -= direction.y;
}
}
return null;
}