185 lines
6.0 KiB
C#
185 lines
6.0 KiB
C#
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;
|
|
private bool controlsEnabled = true;
|
|
private bool readyToGetInput = false;
|
|
|
|
[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 int interactionDirection = 0;
|
|
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;
|
|
}
|
|
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
if (controlsEnabled && readyToGetInput)
|
|
{
|
|
SelectedSetting.InteractView(interactionDirection);
|
|
}
|
|
|
|
SmoothScrollToSelected();
|
|
DisplayPointer();
|
|
interactionDirection = 0;
|
|
}
|
|
|
|
public void _ChangeInteractionDirection(int delta) => interactionDirection += delta;
|
|
public void EnableControls() => controlsEnabled = true;
|
|
public void DisableControls() => controlsEnabled = false;
|
|
public void SetReadyToGetInput() => readyToGetInput = true;
|
|
|
|
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;
|
|
}
|
|
|
|
public void SwitchItem(int direction)
|
|
{
|
|
if (direction == 0 || !controlsEnabled) 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;
|
|
}
|
|
} |