chip-gameV3/Assets/Scripts/Settings/SettingsScreen.cs

200 lines
6.0 KiB
C#

using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class SettingsScreen : MonoBehaviour, IControlable
{
[SerializeField] private MenuSettingsTransit _menuSettingsTransit;
[Header("Ссылки")]
[SerializeField] private SettingGroup GroupPrefab;
private int activeSettingIndex;
private List<BaseSettingView> settings;
[SerializeField] RectTransform _testPointer;
[SerializeField] CanvasGroup _pointerCG;
[SerializeField] ScrollRect scrollRect;
[SerializeField] TextMeshProUGUI _description;
[Header("Управление")]
[SerializeField] private Axis switchAxis = Axis.Vertical;
[SerializeField] private Axis interactAxis = Axis.Horizontal;
[SerializeField] private PlayerAction intractButton = PlayerAction.action;
[SerializeField] private float _switchRepeatInterval = 0.2f;
[SerializeField] private RectTransform _rootRect;
[SerializeField] private RectTransform Content;
[SerializeField] RectTransform _scrollBar;
private BaseSettingView SelectedSetting => settings[activeSettingIndex];
private HoldTimer _exitTimer;
public bool ControlsEnabled { get; set; } = false;
private bool controlsBlocked = false;
private int _heldSwitchDirection;
private float _nextSwitchTime;
private void Start()
{
print("Start settings");
Generate();
UpdatePointer();
}
private void OnDisable()
{
_exitTimer.Reset();
ResetSwitchRepeat();
}
public void UpdateControls()
{
if(controlsBlocked && In.GetAction(JoystickSide.Both, InteractMode.Continious) == false)
controlsBlocked = false;
if (controlsBlocked)
{
ResetSwitchRepeat();
return;
}
int switchDirection = GetSwitchDirection();
if (switchDirection != 0)
SwitchSetting(switchDirection);
Vector2Int interactAxes = In.GetAxis(JoystickSide.Both, InteractMode.Continious);
int interactDirection = GetAxisValue(interactAxes, interactAxis);
bool action = In.GetAction(JoystickSide.Both, InteractMode.Continious);
SelectedSetting.TakeInput(interactDirection, action);
if(_exitTimer.Update(In.GetService()))
{
_menuSettingsTransit.GotoMenu();
}
}
private static int GetAxisValue(Vector2Int axes, Axis axis)
=> axis == Axis.Horizontal ? axes.x : axes.y;
public void Generate()
{
ClearContent();
settings = new List<BaseSettingView>();
foreach (var group in SettingsManager.currentSchemeDTO.groups)
settings.AddRange(GenerateGroup(group).settings);
_exitTimer = new HoldTimer(1);
ControlsEnabled = true;
}
public void BlockControls()
{
controlsBlocked = true;
ResetSwitchRepeat();
}
private void SwitchSetting(int switchDirection)
{
SelectedSetting.Deselect();
activeSettingIndex = (activeSettingIndex + switchDirection + settings.Count) % settings.Count;
SelectedSetting.Select();
_description.text = SelectedSetting.CachedSetting.Description;
UpdatePointer();
}
private int GetSwitchDirection()
{
Vector2Int switchAxes = In.GetAxis(JoystickSide.Both, InteractMode.Continious);
int switchDirection = -GetAxisValue(switchAxes, switchAxis);
return UpdateSwitchRepeat(switchDirection, Time.unscaledTime);
}
private int UpdateSwitchRepeat(int switchDirection, float currentTime)
{
if (switchDirection == 0)
{
ResetSwitchRepeat();
return 0;
}
if (switchDirection != _heldSwitchDirection)
{
_heldSwitchDirection = switchDirection;
_nextSwitchTime = currentTime + _switchRepeatInterval;
return switchDirection;
}
if (currentTime < _nextSwitchTime)
return 0;
_nextSwitchTime = currentTime + _switchRepeatInterval;
return switchDirection;
}
private void ResetSwitchRepeat()
{
_heldSwitchDirection = 0;
_nextSwitchTime = 0f;
}
private void UpdatePointer()
{
var activePivot = SelectedSetting.pivotPoint;
ScrollToElementVertical(activePivot);
_testPointer.position = activePivot.position;
_pointerCG.alpha = SelectedSetting is SignalView ? 0 : 1;
_scrollBar.anchoredPosition = new Vector2(0, -460f * activeSettingIndex / (settings.Count-1));
}
private SettingGroup GenerateGroup(SettingsGroupDTO groupData)
{
var group = Instantiate(GroupPrefab, Content);
group.Configure(groupData);
return group;
}
private void ClearContent()
{
for (int i = Content.childCount - 1; i >= 0; i--)
Destroy(Content.GetChild(i).gameObject);
}
private void ScrollToElementVertical(RectTransform targetRect)
{
LayoutRebuilder.ForceRebuildLayoutImmediate(scrollRect.content);
RectTransform viewport = scrollRect.viewport;
RectTransform content = scrollRect.content;
Vector2 targetLocalPos = content.InverseTransformPoint(targetRect.position);
Vector2 viewportLocalPos = content.InverseTransformPoint(viewport.position);
float targetHeight = targetRect.rect.height;
float viewportHeight = viewport.rect.height;
float contentHeight = content.rect.height;
if (contentHeight <= viewportHeight)
{
scrollRect.verticalNormalizedPosition = 1f;
return;
}
float offsetY = (targetLocalPos.y - viewportLocalPos.y) * -1f;
float targetCenterY = offsetY + targetHeight * 0.5f;
float viewportCenterY = viewportHeight * 0.5f;
float deltaY = (targetCenterY - viewportCenterY) / (contentHeight - viewportHeight);
float newPosition = Mathf.Clamp01(scrollRect.verticalNormalizedPosition - deltaY);
scrollRect.verticalNormalizedPosition = newPosition;
}
}