diff --git a/Silksong.ModMenu/Directory.Build.props b/Silksong.ModMenu/Directory.Build.props index 1340085..8fe9e05 100644 --- a/Silksong.ModMenu/Directory.Build.props +++ b/Silksong.ModMenu/Directory.Build.props @@ -11,6 +11,6 @@ It should follow the format major.minor.patch (semantic versioning). If you publish your mod as a library to NuGet, this version will also be used as the package version. --> - 0.7.4 + 0.8.0 diff --git a/Silksong.ModMenu/Elements/AbstractGroup.cs b/Silksong.ModMenu/Elements/AbstractGroup.cs index 915b891..b87891d 100644 --- a/Silksong.ModMenu/Elements/AbstractGroup.cs +++ b/Silksong.ModMenu/Elements/AbstractGroup.cs @@ -60,19 +60,19 @@ protected AbstractGroup() protected abstract IEnumerable GetNavigables(NavigationDirection direction); /// - public virtual void ClearNeighbor(NavigationDirection direction) + public virtual void ClearNeighbors(NavigationDirection direction) { foreach (var navigable in GetNavigables(direction)) - navigable.ClearNeighbor(direction); + navigable.ClearNeighbors(direction); } /// public virtual void ClearNeighbors() { - ClearNeighbor(NavigationDirection.Up); - ClearNeighbor(NavigationDirection.Left); - ClearNeighbor(NavigationDirection.Right); - ClearNeighbor(NavigationDirection.Down); + ClearNeighbors(NavigationDirection.Up); + ClearNeighbors(NavigationDirection.Left); + ClearNeighbors(NavigationDirection.Right); + ClearNeighbors(NavigationDirection.Down); } /// @@ -85,9 +85,9 @@ public virtual void ClearNeighbors() .FirstOrDefault(); /// - public abstract bool GetSelectable( + public abstract bool GetSelectables( NavigationDirection direction, - [MaybeNullWhen(false)] out Selectable selectable + [MaybeNullWhen(false)] out IEnumerable selectables ); private GameObject? gameObjectParent; @@ -113,10 +113,13 @@ public virtual void ClearGameObjectParent() } /// - public virtual void SetNeighbor(NavigationDirection direction, Selectable selectable) + public virtual void SetNeighbors( + NavigationDirection direction, + IEnumerable selectables + ) { foreach (var navigable in GetNavigables(direction)) - navigable.SetNeighbor(direction, selectable); + navigable.SetNeighbors(direction, selectables); } /// diff --git a/Silksong.ModMenu/Elements/FreeGroup.cs b/Silksong.ModMenu/Elements/FreeGroup.cs index bac9da0..2eec70e 100644 --- a/Silksong.ModMenu/Elements/FreeGroup.cs +++ b/Silksong.ModMenu/Elements/FreeGroup.cs @@ -88,15 +88,14 @@ private static float SortKey(NavigationDirection direction, Vector2 pos) => }; /// - public override bool GetSelectable( + public override bool GetSelectables( NavigationDirection direction, - [MaybeNullWhen(false)] out Selectable selectable + [MaybeNullWhen(false)] out IEnumerable selectables ) { - selectable = GetNavigables(direction) - .Select(n => n.GetSelectable(direction, out var s) ? s : null) - .FirstOrDefault(); - return selectable != null; + selectables = GetNavigables(direction.Opposite()) + .SelectMany(n => n.GetSelectables(direction, out var s) ? s : []); + return selectables.Any(); } /// diff --git a/Silksong.ModMenu/Elements/GridGroup.cs b/Silksong.ModMenu/Elements/GridGroup.cs index b08b7f6..e06bcf2 100644 --- a/Silksong.ModMenu/Elements/GridGroup.cs +++ b/Silksong.ModMenu/Elements/GridGroup.cs @@ -150,36 +150,30 @@ public override void Clear() } /// - public override bool GetSelectable( + public override bool GetSelectables( NavigationDirection direction, - [MaybeNullWhen(false)] out Selectable selectable + [MaybeNullWhen(false)] out IEnumerable selectables ) { - var navigable = direction switch + var navigables = direction switch { - // Last element. - NavigationDirection.Up => AllEntities() - .Where(e => e.VisibleSelf) - .OfType() - .LastOrDefault(), - // Rightmost element. - NavigationDirection.Left => GetColumns() - .SelectMany(col => col.WhereNonNull(e => e.VisibleSelf).OfType()) - .LastOrDefault(), - // Leftmost element. - NavigationDirection.Right => GetColumns() - .SelectMany(col => col.WhereNonNull(e => e.VisibleSelf).OfType()) - .FirstOrDefault(), - // First element. - NavigationDirection.Down => AllEntities() - .Where(e => e.VisibleSelf) - .OfType() - .FirstOrDefault(), + // Bottommost element of every column. + NavigationDirection.Up => GetColumns() + .Select(x => (INavigable?)x.LastOrDefault(e => e is INavigable && e.VisibleSelf)) + .WhereNonNull(), + // Rightmost element of every row. + NavigationDirection.Left => GetNavigables(NavigationDirection.Right), + // Leftmost element of every row. + NavigationDirection.Right => GetNavigables(NavigationDirection.Left), + // Topmost element of every column. + NavigationDirection.Down => GetColumns() + .Select(x => (INavigable?)x.FirstOrDefault(e => e is INavigable && e.VisibleSelf)) + .WhereNonNull(), _ => throw new ArgumentException($"{direction}"), }; - selectable = default; - return navigable != null && navigable.GetSelectable(direction, out selectable); + selectables = navigables.SelectMany(x => x.GetSelectables(direction, out var s) ? s : []); + return selectables.Any(); } /// @@ -216,7 +210,7 @@ static bool ClosestColumn( INavigable?[] row, NavigationDirection dir, int column, - [MaybeNullWhen(false)] out Selectable target + [MaybeNullWhen(false)] out IEnumerable targets ) { int offset = 0; @@ -235,12 +229,12 @@ static bool ClosestColumn( if ( idx >= 0 && idx < row.Length - && (row[idx]?.GetSelectable(dir, out target) ?? false) + && (row[idx]?.GetSelectables(dir, out targets) ?? false) ) return true; } - target = default; + targets = default; return false; } @@ -250,12 +244,12 @@ static bool ClosestColumn( prevRow[i] != null && ClosestColumn(nextRow, NavigationDirection.Down, i, out var s) ) - prevRow[i]!.SetNeighborDown(s); + prevRow[i]!.SetNeighborsDown(s); if ( nextRow[i] != null && ClosestColumn(prevRow, NavigationDirection.Up, i, out s) ) - nextRow[i]!.SetNeighborUp(s); + nextRow[i]!.SetNeighborsUp(s); } } prevRow = nextRow; diff --git a/Silksong.ModMenu/Elements/INavigable.cs b/Silksong.ModMenu/Elements/INavigable.cs index 05134db..e38ae18 100644 --- a/Silksong.ModMenu/Elements/INavigable.cs +++ b/Silksong.ModMenu/Elements/INavigable.cs @@ -1,4 +1,6 @@ -using System.Diagnostics.CodeAnalysis; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using UnityEngine.UI; namespace Silksong.ModMenu.Elements; @@ -14,25 +16,25 @@ public interface INavigable void ClearNeighbors(); /// - /// Set the directional neighbor of this entity. + /// Set the directional neighbors of this entity to one or more of the given choices. /// /// False if this entity has no navigation to connect. - void SetNeighbor(NavigationDirection direction, Selectable selectable); + void SetNeighbors(NavigationDirection direction, IEnumerable selectables); /// /// Unset the given directional neighbor of this entity. /// - void ClearNeighbor(NavigationDirection direction); + void ClearNeighbors(NavigationDirection direction); /// - /// Get the Selectable to target if navigating to this element along 'direction'. + /// Get a set of choices for the Selectables to target if navigating to this element along 'direction'. /// /// In other words, typical usage would entail: - /// if (foo.GetSelectable(dir, out var selectable)) - /// bar.SetNeighbor(dir, selectable); + /// if (foo.GetSelectables(dir, out var selectables)) + /// bar.SetNeighbors(dir, selectables); /// - bool GetSelectable( + bool GetSelectables( NavigationDirection direction, - [MaybeNullWhen(false)] out Selectable selectable + [MaybeNullWhen(false)] out IEnumerable selectables ); } diff --git a/Silksong.ModMenu/Elements/INavigableExtensions.cs b/Silksong.ModMenu/Elements/INavigableExtensions.cs index 8e73dd5..83b54a7 100644 --- a/Silksong.ModMenu/Elements/INavigableExtensions.cs +++ b/Silksong.ModMenu/Elements/INavigableExtensions.cs @@ -1,4 +1,5 @@ -using System.Diagnostics.CodeAnalysis; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using UnityEngine.UI; namespace Silksong.ModMenu.Elements; @@ -14,106 +15,146 @@ public static class INavigableExtensions extension(INavigable self) { /// - /// Set the upwards neighbor of this navigable. + /// Set the upwards neighbors of this navigable. /// - public void SetNeighborUp(Selectable selectable) => - self.SetNeighbor(NavigationDirection.Up, selectable); + public void SetNeighborsUp(Selectable selectable) => + self.SetNeighbors(NavigationDirection.Up, [selectable]); /// - /// Set the upwards neighbor of this navigable. + /// Set the upwards neighbors of this navigable to one or more of the given options. /// - public void SetNeighborUp(SelectableElement selectableElement) => - self.SetNeighborUp(selectableElement.SelectableComponent); + public void SetNeighborsUp(IEnumerable selectables) => + self.SetNeighbors(NavigationDirection.Up, selectables); /// - /// Declare that this navigable has no upwards neighbor. + /// Set the upwards neighbors of this navigable. /// - public void ClearNeighborUp() => self.ClearNeighbor(NavigationDirection.Up); + public void SetNeighborsUp(SelectableElement selectableElement) + { + if (selectableElement.GetSelectables(NavigationDirection.Up, out var selectables)) + self.SetNeighborsUp(selectables); + } + + /// + /// Declare that this navigable has no upwards neighbors. + /// + public void ClearNeighborsUp() => self.ClearNeighbors(NavigationDirection.Up); + + /// + /// Get the most eligible selectables within this navigable when navigating upwards into it. + /// + public bool GetNeighborsUp( + [MaybeNullWhen(false)] out IEnumerable selectables + ) => self.GetSelectables(NavigationDirection.Up, out selectables); + + /// + /// Set the leftwards neighbors of this navigable. + /// + public void SetNeighborsLeft(Selectable selectable) => + self.SetNeighbors(NavigationDirection.Left, [selectable]); /// - /// Get the most eligible selectable within this navigable when navigating upwards into it. + /// Set the leftwards neighbors of this navigable to one or more of the given options. /// - public bool GetNeighborUp([MaybeNullWhen(false)] out Selectable selectable) => - self.GetSelectable(NavigationDirection.Up, out selectable); + public void SetNeighborsLeft(IEnumerable selectables) => + self.SetNeighbors(NavigationDirection.Left, selectables); /// - /// Set the leftwards neighbor of this navigable. + /// Set the leftwards neighbors of this navigable. /// - public void SetNeighborLeft(Selectable selectable) => - self.SetNeighbor(NavigationDirection.Left, selectable); + public void SetNeighborsLeft(SelectableElement selectableElement) + { + if (selectableElement.GetSelectables(NavigationDirection.Left, out var selectables)) + self.SetNeighborsLeft(selectables); + } /// - /// Set the leftwards neighbor of this navigable. + /// Declare that this navigable has no upwards neighbors. /// - public void SetNeighborLeft(SelectableElement selectableElement) => - self.SetNeighborLeft(selectableElement.SelectableComponent); + public void ClearNeighborsLeft() => self.ClearNeighbors(NavigationDirection.Left); /// - /// Declare that this navigable has no upwards neighbor. + /// Get the most eligible selectables within this navigable when navigating leftwards into it. /// - public void ClearNeighborLeft() => self.ClearNeighbor(NavigationDirection.Left); + public bool GetNeighborsLeft( + [MaybeNullWhen(false)] out IEnumerable selectables + ) => self.GetSelectables(NavigationDirection.Left, out selectables); /// - /// Get the most eligible selectable within this navigable when navigating leftwards into it. + /// Set the rightwards neighbors of this navigable. /// - public bool GetNeighborLeft([MaybeNullWhen(false)] out Selectable selectable) => - self.GetSelectable(NavigationDirection.Left, out selectable); + public void SetNeighborsRight(Selectable selectable) => + self.SetNeighbors(NavigationDirection.Right, [selectable]); /// - /// Set the rightwards neighbor of this navigable. + /// Set the rightwards neighbors of this navigable to one or more of the given options. /// - public void SetNeighborRight(Selectable selectable) => - self.SetNeighbor(NavigationDirection.Right, selectable); + public void SetNeighborsRight(IEnumerable selectables) => + self.SetNeighbors(NavigationDirection.Right, selectables); /// - /// Set the rightwards neighbor of this navigable. + /// Set the rightwards neighbors of this navigable. /// - public void SetNeighborRight(SelectableElement selectableElement) => - self.SetNeighborRight(selectableElement.SelectableComponent); + public void SetNeighborsRight(SelectableElement selectableElement) + { + if (selectableElement.GetSelectables(NavigationDirection.Right, out var selectables)) + self.SetNeighborsRight(selectables); + } /// - /// Get the most eligible selectable within this navigable when navigating rightwards into it. + /// Get the most eligible selectables within this navigable when navigating rightwards into it. /// - public bool GetNeighborRight([MaybeNullWhen(false)] out Selectable selectable) => - self.GetSelectable(NavigationDirection.Right, out selectable); + public bool GetNeighborsRight( + [MaybeNullWhen(false)] out IEnumerable selectables + ) => self.GetSelectables(NavigationDirection.Right, out selectables); /// - /// Declare that this navigable has no upwards neighbor. + /// Declare that this navigable has no upwards neighbors. /// - public void ClearNeighborRight() => self.ClearNeighbor(NavigationDirection.Right); + public void ClearNeighborsRight() => self.ClearNeighbors(NavigationDirection.Right); /// - /// Set the downwards neighbor of this navigable. + /// Set the downwards neighbors of this navigable. /// public void SetNeighborDown(Selectable selectable) => - self.SetNeighbor(NavigationDirection.Down, selectable); + self.SetNeighbors(NavigationDirection.Down, [selectable]); /// - /// Set the downwards neighbor of this navigable. + /// Set the downwards neighbors of this navigable to one or more of the given options. /// - public void SetNeighborDown(SelectableElement selectableElement) => - self.SetNeighborDown(selectableElement.SelectableComponent); + public void SetNeighborsDown(IEnumerable selectables) => + self.SetNeighbors(NavigationDirection.Down, selectables); + + /// + /// Set the downwards neighbors of this navigable. + /// + public void SetNeighborsDown(SelectableElement selectableElement) + { + if (selectableElement.GetSelectables(NavigationDirection.Down, out var selectables)) + self.SetNeighborsDown(selectables); + } /// - /// Declare that this navigable has no upwards neighbor. + /// Declare that this navigable has no upwards neighbors. /// - public void ClearNeighborDown() => self.ClearNeighbor(NavigationDirection.Down); + public void ClearNeighborsDown() => self.ClearNeighbors(NavigationDirection.Down); /// - /// Get the most eligible selectable within this navigable when navigating downwards into it. + /// Get the most eligible selectables within this navigable when navigating downwards into it. /// - public bool GetNeighborDown([MaybeNullWhen(false)] out Selectable selectable) => - self.GetSelectable(NavigationDirection.Down, out selectable); + public bool GetNeighborsDown( + [MaybeNullWhen(false)] out IEnumerable selectables + ) => self.GetSelectables(NavigationDirection.Down, out selectables); /// /// Symmetrically connect two INavigables. /// public void ConnectSymmetric(INavigable dest, NavigationDirection direction) { - if (dest.GetSelectable(direction, out var s)) - self.SetNeighbor(direction, s); - if (self.GetSelectable(direction.Opposite(), out s)) - dest.SetNeighbor(direction.Opposite(), s); + if (dest.GetSelectables(direction, out var s)) + self.SetNeighbors(direction, s); + if (self.GetSelectables(direction.Opposite(), out s)) + dest.SetNeighbors(direction.Opposite(), s); } } } diff --git a/Silksong.ModMenu/Elements/ScrollingPane.cs b/Silksong.ModMenu/Elements/ScrollingPane.cs index d1b1051..14fa9ac 100644 --- a/Silksong.ModMenu/Elements/ScrollingPane.cs +++ b/Silksong.ModMenu/Elements/ScrollingPane.cs @@ -288,20 +288,20 @@ Func shouldSkip public void ClearNeighbors() => Content?.ClearNeighbors(); /// - public void SetNeighbor(NavigationDirection direction, Selectable selectable) => - Content?.SetNeighbor(direction, selectable); + public void SetNeighbors(NavigationDirection direction, IEnumerable selectables) => + Content?.SetNeighbors(direction, selectables); /// - public void ClearNeighbor(NavigationDirection direction) => Content?.ClearNeighbor(direction); + public void ClearNeighbors(NavigationDirection direction) => Content?.ClearNeighbors(direction); /// - public bool GetSelectable( + public bool GetSelectables( NavigationDirection direction, - [MaybeNullWhen(false)] out Selectable selectable + [MaybeNullWhen(false)] out IEnumerable selectables ) { - selectable = default; - return Content?.GetSelectable(direction, out selectable) ?? false; + selectables = default; + return Content?.GetSelectables(direction, out selectables) ?? false; } #endregion diff --git a/Silksong.ModMenu/Elements/SelectableElement.cs b/Silksong.ModMenu/Elements/SelectableElement.cs index b49d9b3..7e4c705 100644 --- a/Silksong.ModMenu/Elements/SelectableElement.cs +++ b/Silksong.ModMenu/Elements/SelectableElement.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Silksong.ModMenu.Internal; using Silksong.ModMenu.Util; @@ -71,20 +72,20 @@ public bool Interactable public void ClearNeighbors() => new SelectableWrapper(SelectableComponent).ClearNeighbors(); /// - public void ClearNeighbor(NavigationDirection direction) => - new SelectableWrapper(SelectableComponent).ClearNeighbor(direction); + public void ClearNeighbors(NavigationDirection direction) => + new SelectableWrapper(SelectableComponent).ClearNeighbors(direction); /// - public void SetNeighbor(NavigationDirection direction, Selectable selectable) => - new SelectableWrapper(SelectableComponent).SetNeighbor(direction, selectable); + public void SetNeighbors(NavigationDirection direction, IEnumerable selectables) => + new SelectableWrapper(SelectableComponent).SetNeighbors(direction, selectables); /// - public bool GetSelectable( + public bool GetSelectables( NavigationDirection direction, - [MaybeNullWhen(false)] out Selectable selectable + [MaybeNullWhen(false)] out IEnumerable selectables ) { - selectable = SelectableComponent; + selectables = [SelectableComponent]; return true; } diff --git a/Silksong.ModMenu/Elements/VerticalGroup.cs b/Silksong.ModMenu/Elements/VerticalGroup.cs index c756f93..3c9af31 100644 --- a/Silksong.ModMenu/Elements/VerticalGroup.cs +++ b/Silksong.ModMenu/Elements/VerticalGroup.cs @@ -89,33 +89,31 @@ public override void Clear() } /// - public override bool GetSelectable( + public override bool GetSelectables( NavigationDirection direction, - [MaybeNullWhen(false)] out Selectable selectable + [MaybeNullWhen(false)] out IEnumerable selectables ) { switch (direction) { case NavigationDirection.Left: case NavigationDirection.Right: - selectable = NonHiddenEntities() - .MedianOutwards() + selectables = NonHiddenEntities() .OfType() - .Select(n => n.GetSelectable(direction, out var s) ? s : null) - .FirstOrDefault(); - return selectable != null; + .SelectMany(n => n.GetSelectables(direction, out var s) ? s : null); + return selectables != null; case NavigationDirection.Up: - selectable = NonHiddenEntities() + selectables = NonHiddenEntities() .OfType() - .Select(n => n.GetSelectable(direction, out var s) ? s : null) + .Select(n => n.GetSelectables(direction, out var s) ? s : null) .LastOrDefault(); - return selectable != null; + return selectables != null; case NavigationDirection.Down: - selectable = NonHiddenEntities() + selectables = NonHiddenEntities() .OfType() - .Select(n => n.GetSelectable(direction, out var s) ? s : null) + .Select(n => n.GetSelectables(direction, out var s) ? s : null) .FirstOrDefault(); - return selectable != null; + return selectables != null; default: throw direction.UnsupportedEnum(); } diff --git a/Silksong.ModMenu/Internal/SelectableWrapper.cs b/Silksong.ModMenu/Internal/SelectableWrapper.cs index 597fdc3..36f690d 100644 --- a/Silksong.ModMenu/Internal/SelectableWrapper.cs +++ b/Silksong.ModMenu/Internal/SelectableWrapper.cs @@ -1,5 +1,9 @@ -using System.Diagnostics.CodeAnalysis; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; using Silksong.ModMenu.Elements; +using UnityEngine; using UnityEngine.UI; namespace Silksong.ModMenu.Internal; @@ -19,7 +23,7 @@ private Navigation Nav }; } - public void ClearNeighbor(NavigationDirection direction) => + public void ClearNeighbors(NavigationDirection direction) => Nav = direction switch { NavigationDirection.Up => Nav with { selectOnUp = null }, @@ -31,22 +35,72 @@ public void ClearNeighbor(NavigationDirection direction) => public void ClearNeighbors() => Nav = new(); - public bool GetSelectable( + public bool GetSelectables( NavigationDirection direction, - [MaybeNullWhen(false)] out Selectable selectable + [MaybeNullWhen(false)] out IEnumerable selectables ) { - selectable = this.selectable; + selectables = [selectable]; return true; } - public void SetNeighbor(NavigationDirection direction, Selectable selectable) => + public void SetNeighbors(NavigationDirection direction, IEnumerable selectables) + { + if (!selectables.Any()) + throw new ArgumentException( + "At least one selectable is required.", + nameof(selectables) + ); + + Vector2 thisPosition = selectable.transform.position; + Vector2 directionVector = direction switch + { + NavigationDirection.Up => Vector2.up, + NavigationDirection.Left => Vector2.left, + NavigationDirection.Right => Vector2.right, + NavigationDirection.Down => Vector2.down, + _ => throw direction.UnsupportedEnum(), + }; + + Selectable bestOption = selectables + .Select(selectable => + { + Vector2 otherPosition = selectable.transform.position, + angleBetweenSelectables = otherPosition - thisPosition; + + float angleRelativeToDirection = Vector2.Angle( + directionVector, + angleBetweenSelectables + ), + angleRelativeToOpposite = Vector2.Angle( + -directionVector, + angleBetweenSelectables + ); + + return ( + selectable, + angleRelativeToDirection, + angleRelativeToAxis: Mathf.Min( + angleRelativeToDirection, + angleRelativeToOpposite + ), + position: otherPosition + ); + }) + // Favour selectables on the correct side of this one, narrow down by how well aligned they are with the current selectable + .OrderBy(other => (int)Mathf.RoundToMultipleOf(other.angleRelativeToDirection, 180)) + .ThenBy(other => (int)Mathf.RoundToMultipleOf(other.angleRelativeToAxis, 20)) + .ThenBy(other => Vector2.Distance(thisPosition, other.position)) + .First() + .selectable; + Nav = direction switch { - NavigationDirection.Up => Nav with { selectOnUp = selectable }, - NavigationDirection.Left => Nav with { selectOnLeft = selectable }, - NavigationDirection.Right => Nav with { selectOnRight = selectable }, - NavigationDirection.Down => Nav with { selectOnDown = selectable }, + NavigationDirection.Up => Nav with { selectOnUp = bestOption }, + NavigationDirection.Left => Nav with { selectOnLeft = bestOption }, + NavigationDirection.Right => Nav with { selectOnRight = bestOption }, + NavigationDirection.Down => Nav with { selectOnDown = bestOption }, _ => throw direction.UnsupportedEnum(), }; + } } diff --git a/Silksong.ModMenu/Screens/BasicMenuScreen.cs b/Silksong.ModMenu/Screens/BasicMenuScreen.cs index 4a3bcf0..be90e2e 100644 --- a/Silksong.ModMenu/Screens/BasicMenuScreen.cs +++ b/Silksong.ModMenu/Screens/BasicMenuScreen.cs @@ -62,10 +62,10 @@ protected override void UpdateLayout() wrapper.ClearNeighbors(); Content.SetNeighborDown(BackButton); - Content.SetNeighborUp(BackButton); - if (Content.GetNeighborDown(out var selectable)) - wrapper.SetNeighborDown(selectable); - if (Content.GetNeighborUp(out selectable)) - wrapper.SetNeighborUp(selectable); + Content.SetNeighborsUp(BackButton); + if (Content.GetNeighborsDown(out var selectables)) + wrapper.SetNeighborsDown(selectables); + if (Content.GetNeighborsUp(out selectables)) + wrapper.SetNeighborsUp(selectables); } } diff --git a/Silksong.ModMenu/Screens/PaginatedMenuScreen.cs b/Silksong.ModMenu/Screens/PaginatedMenuScreen.cs index cd37588..e08f251 100644 --- a/Silksong.ModMenu/Screens/PaginatedMenuScreen.cs +++ b/Silksong.ModMenu/Screens/PaginatedMenuScreen.cs @@ -140,10 +140,10 @@ protected override void UpdateLayout() s.ClearNeighbors(); foreach (var (top, bot) in column.CircularPairs()) { - if (top.GetNeighborUp(out var s)) - bot.SetNeighborUp(s); - if (bot.GetNeighborDown(out s)) - top.SetNeighborDown(s); + if (top.GetNeighborsUp(out var s)) + bot.SetNeighborsUp(s); + if (bot.GetNeighborsDown(out s)) + top.SetNeighborsDown(s); } } } diff --git a/Silksong.ModMenuTesting/Tests/ScrollingPaneTests.cs b/Silksong.ModMenuTesting/Tests/ScrollingPaneTests.cs index e8bb103..b471b9d 100644 --- a/Silksong.ModMenuTesting/Tests/ScrollingPaneTests.cs +++ b/Silksong.ModMenuTesting/Tests/ScrollingPaneTests.cs @@ -32,33 +32,33 @@ internal override AbstractMenuScreen BuildMenuScreen() /// static GridGroup ScrollPaneSiblings() { - VerticalGroup innerContentOne = new(), - innerContentTwo = new(); + VerticalGroup contentOne = new() { VerticalSpacing = SpacingConstants.VSPACE_LARGE }, + contentTwo = new() { VerticalSpacing = SpacingConstants.VSPACE_MEDIUM }, + contentFour = new() { VerticalSpacing = SpacingConstants.VSPACE_SMALL }; - for (int i = 1; i <= 15; i++) + GridGroup contentThree = new(2) { HorizontalSpacing = 240 }; + + for (int i = 1; i <= 6; i++) { - innerContentOne.Add(new TextButton($"Hollow {i}")); - innerContentTwo.Add(new TextButton($"Knight {i}")); + contentOne.Add(new TextButton($"Hollow {i}")); + contentFour.Add(new TextButton($"Silksong {i}")); + } + for (int i = 1; i <= 12; i++) + { + contentTwo.Add(new TextButton($"Knight {i}")); + contentThree.Add(new TextButton($"Yay {i}")); } - ScrollingPane innerScrollOne = - new(innerContentOne) - { - ViewportSize = new Vector2(500, 875), - SmoothScrollTime = 0.5f, - }, - innerScrollTwo = - new(innerContentTwo) - { - ViewportSize = new Vector2(500, 875), - SmoothScrollTime = 0.5f, - }; + ScrollingPane scrollOne = new(contentOne) { ViewportSize = new Vector2(500, 675) }, + scrollTwo = new(contentTwo) { ViewportSize = new Vector2(500, 675) }; - GridGroup outerContent = new(2) { HorizontalSpacing = 600 }; - outerContent.Add(innerScrollOne); - outerContent.Add(innerScrollTwo); + GridGroup outer = new(4) { HorizontalSpacing = SpacingConstants.HSPACE_SMALL }; + outer.Add(scrollOne); + outer.Add(scrollTwo); + outer.Add(contentThree); + outer.Add(contentFour); - return outerContent; + return outer; } ///