diff --git a/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/ItemUi/ItemSlotUi.cs b/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/ItemUi/ItemSlotUi.cs index 5932d68b3..cb28a31fd 100644 --- a/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/ItemUi/ItemSlotUi.cs +++ b/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/ItemUi/ItemSlotUi.cs @@ -6,15 +6,16 @@ namespace DDD { - public class ItemSlotUi : MonoBehaviour, ISelectHandler + public class ItemSlotUi : MonoBehaviour, ISelectHandler, IAutoScrollItem { + [field: SerializeField] public RectTransform RectTransform { get; private set; } [SerializeField] private Button _button; [SerializeField] private Image _backgroundImage; [SerializeField] private Image _icon; [SerializeField] private TextMeshProUGUI _countText; [SerializeField] private Image _markImage; [SerializeField] private Animator _animator; - + [field: SerializeField] public ItemViewModel Model { get; private set; } public IItemSlotUiStrategy Strategy { get; private set; } diff --git a/Assets/_DDD/_Scripts/GameUi/ScrollViewUi/AutoScrollToSelected.cs b/Assets/_DDD/_Scripts/GameUi/ScrollViewUi/AutoScrollToSelected.cs new file mode 100644 index 000000000..c564ff9cc --- /dev/null +++ b/Assets/_DDD/_Scripts/GameUi/ScrollViewUi/AutoScrollToSelected.cs @@ -0,0 +1,106 @@ +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +namespace DDD +{ + public class AutoScrollToSelected : MonoBehaviour + { + private ScrollRect _scrollRect; + private RectTransform _viewport; + private RectTransform _content; + + private GameObject _lastSelected; + private bool _wasScrolling; + + private void Awake() + { + _scrollRect = GetComponent(); + _viewport = _scrollRect.viewport; + _content = _scrollRect.content; + } + + private void Update() + { + if (_scrollRect.velocity.sqrMagnitude > 0.01f) + { + _wasScrolling = true; + return; + } + + if (_wasScrolling) + { + _wasScrolling = false; + return; + } + + var selected = EventSystem.current.currentSelectedGameObject; + if (selected == null || selected == _lastSelected) return; + _lastSelected = selected; + + if (!selected.TryGetComponent(out var autoScrollItem)) return; + + var target = autoScrollItem.RectTransform; + if (!target.IsChildOf(_content)) return; + + if (!IsFullyVisible(target)) + { + ScrollToMakeFullyVisible(target); + } + } + + private bool IsFullyVisible(RectTransform target) + { + var worldCorners = new Vector3[4]; + target.GetWorldCorners(worldCorners); + + for (int i = 0; i < 4; i++) + { + Vector3 local = _viewport.InverseTransformPoint(worldCorners[i]); + if (!_viewport.rect.Contains(local)) return false; + } + + return true; + } + + private void ScrollToMakeFullyVisible(RectTransform target) + { + Canvas.ForceUpdateCanvases(); + + float scrollRange = _content.rect.height - _viewport.rect.height; + if (scrollRange <= 0f) return; + + Vector3[] itemCorners = new Vector3[4]; + target.GetWorldCorners(itemCorners); + Vector3[] viewportCorners = new Vector3[4]; + _viewport.GetWorldCorners(viewportCorners); + + float itemTop = itemCorners[1].y; + float itemBottom = itemCorners[0].y; + float viewTop = viewportCorners[1].y; + float viewBottom = viewportCorners[0].y; + + float offset = 0f; + float normalizedDelta = 0f; + + if (itemTop > viewTop) + { + offset = itemTop - viewTop; + normalizedDelta = offset / scrollRange; + _scrollRect.verticalNormalizedPosition += normalizedDelta; + } + else if (itemBottom < viewBottom) + { + offset = viewBottom - itemBottom; + normalizedDelta = offset / scrollRange; + _scrollRect.verticalNormalizedPosition -= normalizedDelta; + } + else + { + return; + } + + _scrollRect.verticalNormalizedPosition = Mathf.Clamp01(_scrollRect.verticalNormalizedPosition); + } + } +} diff --git a/Assets/_DDD/_Scripts/GameUi/ScrollViewUi/IAutoScrollItem.cs b/Assets/_DDD/_Scripts/GameUi/ScrollViewUi/IAutoScrollItem.cs new file mode 100644 index 000000000..7ea357df4 --- /dev/null +++ b/Assets/_DDD/_Scripts/GameUi/ScrollViewUi/IAutoScrollItem.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +namespace DDD +{ + public interface IAutoScrollItem + { + RectTransform RectTransform { get; } + } +} \ No newline at end of file