sea-battle-vr/Assets/Scripts/Settings/SettingsScreen.cs

190 lines
6.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SettingsScreen : MonoBehaviour
{
public List<SettingsGroup> TestSettingGroups;
[SerializeField] private SettingGroupView GroupViewPrefab;
[SerializeField] RectTransform pointer;
[SerializeField] private ScrollRect scrollRect;
[SerializeField] private RectTransform Content;
[Header("Настройки scroll view")]
[SerializeField] private float scrollSmoothTime = 0.2f;
[SerializeField] private bool centerSelectedItem = true; // Центрировать выбранный элемент
SettingView SelectedSetting => settingsGroups[activeGroup].GeneratedSettingViews[activeSetting];
bool Generated = false;
int activeGroup;
int activeSetting;
List<SettingGroupView> settingsGroups;
// Для плавного скролла
private float targetVerticalPosition = 0f;
private float scrollVelocity = 0f;
private void OnEnable()
{
Generate(TestSettingGroups);
}
private void Update()
{
if (!Generated) return;
// Навигация по элементам
if (Input.GetKeyDown(KeyCode.Space)) SwitchItem();
int dir = 0;
if (Input.GetKey(KeyCode.LeftArrow)) dir -= 1;
if (Input.GetKey(KeyCode.RightArrow)) dir += 1;
SelectedSetting.InteractView(dir);
// Плавный скролл к выбранному элементу
if (centerSelectedItem)
{
SmoothScrollToSelected();
}
DisplayPointer();
}
void SwitchItem()
{
activeSetting++;
SettingGroupView currentGroup = settingsGroups[activeGroup];
if (activeSetting > currentGroup.GeneratedSettingViews.Count - 1)
{
activeGroup = (activeGroup + 1 + settingsGroups.Count) % settingsGroups.Count;
activeSetting = 0;
}
UpdateScrollTarget();
// Отладка
Debug.Log($"Switched to Group: {activeGroup}, Setting: {activeSetting}");
}
void DisplayPointer()
{
pointer.parent= SelectedSetting.transform;
pointer.localPosition = Vector3.zero;
}
public void Generate(List<SettingsGroup> groups)
{
// Очищаем старые группы
if (settingsGroups != null)
{
foreach (var group in settingsGroups)
{
if (group != null)
Destroy(group.gameObject);
}
}
settingsGroups = new List<SettingGroupView>();
foreach (var group in groups)
{
var generatedGroup = GenerateGroup(group);
settingsGroups.Add(generatedGroup);
}
// Сброс индексов
activeGroup = 0;
activeSetting = 0;
DisplayPointer();
Generated = true;
// Обновляем канвас и скролл
Canvas.ForceUpdateCanvases();
UpdateScrollTarget();
// Принудительно применяем позицию скролла
Invoke(nameof(ApplyScrollPosition), 0.1f);
}
private SettingGroupView GenerateGroup(SettingsGroup group)
{
var go = Instantiate(GroupViewPrefab.gameObject, Content);
var groupView = go.GetComponent<SettingGroupView>();
groupView.Generate(group);
return groupView;
}
void UpdateScrollTarget()
{
if (!centerSelectedItem) return;
float targetNormalizedPosition = CalculateNormalizedPosition();
targetVerticalPosition = targetNormalizedPosition;
Debug.Log($"Target position: {targetVerticalPosition}");
}
float CalculateNormalizedPosition()
{
// Проверка наличия необходимых компонентов
if (scrollRect.viewport == null)
{
Debug.LogError("ScrollRect Viewport is not assigned!");
return 0f;
}
RectTransform selectedRect = SelectedSetting.GetComponent<RectTransform>();
// Получаем мировые координаты углов
Vector3[] worldCorners = new Vector3[4];
selectedRect.GetWorldCorners(worldCorners);
// Получаем локальные координаты относительно Content
Vector3 localPos = Content.InverseTransformPoint(worldCorners[1]); // Верхний левый угол элемента
// Вычисляем нормализованную позицию (0 = вверху, 1 = внизу)
float contentHeight = Content.rect.height;
float viewportHeight = scrollRect.viewport.rect.height;
if (contentHeight <= viewportHeight) return 0f;
float maxScroll = contentHeight - viewportHeight;
float scrollPosition = -localPos.y; // Инвертируем, т.к. UI координаты Y вниз
// Центрируем элемент
float elementHeight = selectedRect.rect.height;
scrollPosition -= (viewportHeight / 2f) - (elementHeight / 2f);
float normalizedPosition = Mathf.Clamp01(scrollPosition / maxScroll);
return 1f - normalizedPosition; // Инвертируем для ScrollRect
}
void SmoothScrollToSelected()
{
float currentPos = scrollRect.verticalNormalizedPosition;
float newPos = Mathf.SmoothDamp(currentPos, targetVerticalPosition,
ref scrollVelocity, scrollSmoothTime);
scrollRect.verticalNormalizedPosition = newPos;
}
void ApplyScrollPosition()
{
scrollRect.verticalNormalizedPosition = targetVerticalPosition;
}
// Опционально: принудительное обновление при изменении размеров
private void OnRectTransformDimensionsChange()
{
if (Generated && centerSelectedItem)
{
Canvas.ForceUpdateCanvases();
UpdateScrollTarget();
}
}
}