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

182 lines
5.9 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
{
[Header("Управление")]
[SerializeField] private InSignal NextSetting;
[SerializeField] private InSignal PreviousSetting;
[SerializeField] private InSignal ChangeSettingPositive;
[SerializeField] private InSignal ChangeSettingNegative;
[Header("Ссылки")]
[SerializeField] private SettingGroupView GroupViewPrefab;
[SerializeField] private RectTransform pointer;
[SerializeField] private ScrollRect scrollRect;
[SerializeField] private RectTransform Content;
[Header("Настройки scroll view")]
[SerializeField] private float scrollSmoothTime = 0.2f;
private SettingView SelectedSetting => settingsGroups[activeGroup].GeneratedSettingViews[activeSetting];
private bool Generated = false;
private int activeGroup;
private int activeSetting;
private List<SettingGroupView> settingsGroups;
// Для плавного скролла
private float targetVerticalPosition = 0f;
private float scrollVelocity = 0f;
private bool isFirstFrame = true;
private void Update()
{
if (!Generated) return;
if (isFirstFrame)
{
isFirstFrame = false;
scrollRect.verticalNormalizedPosition = 1f;
UpdateScrollTarget();
return;
}
int dir;
// Навигация по настройкам
dir = 0;
if (In.GetButtonDown(PreviousSetting)) dir -= 1;
if (In.GetButtonDown(NextSetting)) dir += 1;
SwitchItem(dir);
//Взаимодействие с настройками
dir = 0;
if (In.GetButton(ChangeSettingNegative)) dir -= 1;
if (In.GetButton(ChangeSettingPositive)) dir += 1;
SelectedSetting.InteractView(dir);
SmoothScrollToSelected();
DisplayPointer();
}
public void Generate()
{
// Очищаем старые группы
if (settingsGroups != null)
{
foreach (var group in settingsGroups)
{
if (group != null)
Destroy(group.gameObject);
}
}
settingsGroups = new List<SettingGroupView>();
foreach (var group in SettingsManager.currentSchemeDTO.groups)
{
var generatedGroup = GenerateGroup(group);
settingsGroups.Add(generatedGroup);
}
activeGroup = 0;
activeSetting = 0;
Generated = true;
}
private void SwitchItem(int direction)
{
if (direction == 0) return;
activeSetting += direction;
SettingGroupView currentGroup = settingsGroups[activeGroup];
//Выход за пределы группы (верхний предел)
if (activeSetting > currentGroup.GeneratedSettingViews.Count - 1)
{
activeGroup = (activeGroup + 1 + settingsGroups.Count) % settingsGroups.Count;
activeSetting = 0;
}
//Выход за пределы группы (нижний предел)
else if (activeSetting < 0)
{
activeGroup = (activeGroup - 1 + settingsGroups.Count) % settingsGroups.Count;
activeSetting = settingsGroups[activeGroup].GeneratedSettingViews.Count - 1;
}
UpdateScrollTarget();
}
private void DisplayPointer()
{
pointer.parent = SelectedSetting.transform;
pointer.localPosition = Vector3.zero;
}
private SettingGroupView GenerateGroup(SettingsGroupDTO group)
{
var go = Instantiate(GroupViewPrefab.gameObject, Content);
var groupView = go.GetComponent<SettingGroupView>();
groupView.Generate(group);
return groupView;
}
private void UpdateScrollTarget()
{
float targetNormalizedPosition = CalculateNormalizedPosition();
targetVerticalPosition = targetNormalizedPosition;
}
private 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
}
private void SmoothScrollToSelected()
{
float currentPos = scrollRect.verticalNormalizedPosition;
float newPos = Mathf.SmoothDamp(currentPos, targetVerticalPosition,
ref scrollVelocity, scrollSmoothTime);
scrollRect.verticalNormalizedPosition = newPos;
}
}