hellbound/Assets/Scripts/Game/UI/Elements/SliderControl/SliderControl.cs

392 lines
12 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
public class SliderControl : MonoBehaviour
{
public event Action<uint> OnSelectedState;
// [SerializeField] private ParticleSystem _selectPoofPrefab = null;
//[SerializeField] private ParticleSystem _selectGlowPrefab = null;
private int ItemsCount => _itemsDictionary?.Count ?? 0;
private Transform _circleBackgroundsParent;
private Transform _circleForegroundsParent;
private Transform _circleBackgroundTemplate;
private Transform _circleForegroundTemplate;
private Transform[] _circlesForeground;
private Transform[] _circlesBackground;
private Transform _backgroundLine;
//private ParticleSystem _selectPoof = null;
// private ParticleSystem _selectGlow = null;
private Canvas _canvas = null;
private GameObject _itemTemplate = null;
private Slider _slider = null;
private SliderHandle _handle = null;
private Dictionary<uint, SliderItem> _itemsDictionary = null;
private const float SLIDER_SPEED = 20f;
private void Awake()
{
_canvas = UI.Canvas;
_itemTemplate = transform.Find("ItemsPanel/Items/ItemTemplate").gameObject;
_slider = transform.Find("Slider").gameObject.GetComponent<Slider>();
_handle = transform.Find("Slider/Handle Slide Area/Handle").gameObject.GetComponent<SliderHandle>();
_circleBackgroundsParent = transform.Find("ItemsPanel/Background/CircleBackgrounds");
_circleForegroundsParent = transform.Find("ItemsPanel/Background/CircleForegrounds");
_backgroundLine = transform.Find("ItemsPanel/Background/Line");
_circleBackgroundTemplate = _circleBackgroundsParent.Find("CircleTemplate");
_circleBackgroundTemplate.gameObject.SetActive(false);
_circleForegroundTemplate = _circleForegroundsParent.Find("CircleTemplate");
_circleForegroundTemplate.gameObject.SetActive(false);
}
private void Start()
{
// _selectPoof = Instantiate(_selectPoofPrefab, _canvas.transform);
// _selectPoof.Stop();
//
// _selectGlow = Instantiate(_selectGlowPrefab, _handle.transform);
// _selectGlow.Stop();
_handle.SetShowState(false);
}
public void SetControlStates(IReadOnlyList<uint> argument)
{
Refresh();
CreateControls(argument);
// CreateBackgroundCircles(argument.Count);
// CreateForegroundCircles(argument.Count);
CreateCircles(_circleBackgroundTemplate, argument.Count, _circleBackgroundsParent, out _circlesBackground);
CreateCircles(_circleForegroundTemplate, argument.Count, _circleForegroundsParent, out _circlesForeground);
StartCoroutine(SyncLineWidthAfterFrame());
StartCoroutine(SyncSliderWidthAfterFrame());
SetItemListeners();
_itemTemplate.SetActive(false);
}
private IEnumerator SyncLineWidthAfterFrame()
{
yield return null;
SyncLineWidth();
}
private IEnumerator SyncSliderWidthAfterFrame()
{
yield return null;
SyncSliderWidth();
}
private void Refresh()
{
if (ItemsCount == 0)
return;
foreach (SliderItem item in _itemsDictionary.Values)
Destroy(item.gameObject);
_itemsDictionary.Clear();
for (int i = _circlesBackground.Length - 1; i >= 0; i--)
Destroy(_circlesBackground[i].gameObject);
for (int i = _circlesForeground.Length - 1; i >= 0; i--)
Destroy(_circlesForeground[i].gameObject);
_circlesBackground = new Transform[0];
_circlesForeground = new Transform[0];
}
private void CreateControls(IReadOnlyList<uint> states)
{
_itemsDictionary = new Dictionary<uint, SliderItem>();
for (int i = 0; i < states.Count && i < 3; i++)
{
SliderItem item = Instantiate(_itemTemplate, _itemTemplate.transform.parent).AddComponent<SliderItem>();
item.gameObject.SetActive(true);
// как то вытянуть спрайты
// item.SetSpritesForStates(states[i].icon, states[i].icon);
_itemsDictionary.Add(states[i], item);
}
}
private void CreateCircles(Transform prefab, int count, Transform parent, out Transform[] container)
{
container = new Transform[count];
for (int i = 0; i < count; i++)
{
GameObject circle = Instantiate(prefab.gameObject, parent);
circle.SetActive(true);
container[i] = circle.transform;
}
}
private void SyncLineWidth()
{
int itemsCount = 0;
if (_circlesBackground != null)
itemsCount = _circlesBackground.Length;
if (itemsCount == 0)
_backgroundLine.GetComponent<RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 0);
else
{
float xPositionFirstCircle = _circlesBackground[0].GetComponent<RectTransform>().anchoredPosition.x;
float xPositionLastCircle = _circlesBackground[_circlesBackground.Length - 1].GetComponent<RectTransform>().anchoredPosition.x;
_backgroundLine.GetComponent<RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Mathf.Abs(xPositionFirstCircle - xPositionLastCircle));
}
}
private void SyncSliderWidth()
{
int itemsCount = 0;
if (_circlesBackground != null)
itemsCount = _circlesBackground.Length;
if (itemsCount == 0)
_slider.GetComponent<RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 0);
else
{
float xPositionFirstCircle = _circlesBackground[0].GetComponent<RectTransform>().anchoredPosition.x;
float xPositionLastCircle = _circlesBackground[_circlesBackground.Length - 1].GetComponent<RectTransform>().anchoredPosition.x;
_slider.GetComponent<RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Mathf.Abs(xPositionFirstCircle - xPositionLastCircle) + 217);
}
_slider.maxValue = itemsCount == 0 ? 0 : itemsCount - 1;
}
public void SetActiveItemForState(uint state)
{
SliderItem desiredActiveItem = GetButtonFromState(state);
if(desiredActiveItem == null)
return;
SetOnlyActiveItem(desiredActiveItem);
}
private SliderItem GetItem(int index)
{
return _itemsDictionary.Values.ElementAt(index);
}
private void SetItemListeners()
{
for (int i = 0; i < ItemsCount; i++)
GetItem(i).OnClick += OnItemClick;
}
private void Update()
{
#if UNITY_EDITOR
CheckKeyboardInput();
#endif
_handle.SetShowState(HaveActiveItem());
if (!_handle.IsShowing)
return;
if (_handle.HandleIsPressed)
HandleIsPressedUpdate();
else
HandleIsUnpressedUpdate();
}
private void CheckKeyboardInput()
{
#if UNITY_EDITOR
if (Input.GetKeyDown(KeyCode.A))
{
if(ItemsCount < 1)
return;
OnItemClick(GetItem(0));
}
else if (Input.GetKeyDown(KeyCode.S))
{
if(ItemsCount < 2)
return;
OnItemClick(GetItem(1));
}
else if (Input.GetKeyDown(KeyCode.D))
{
if(ItemsCount < 3)
return;
OnItemClick(GetItem(2));
}
#endif
}
private void HandleIsPressedUpdate()
{
float sliderValue = _slider.value;
SliderItem desiredActiveItem = GetDesiredActiveItemFromSliderValue(sliderValue);
SliderItem currentActiveItem = GetActiveItem();
if (desiredActiveItem != currentActiveItem)
{
PlaySelectView(_handle.transform.position, _handle.transform.position);
OnSelectedState?.Invoke(GetStateFromButton(desiredActiveItem));
SetActiveItemForState(GetStateFromButton(desiredActiveItem));
}
}
private void PlaySelectView(Vector3 poofPosition, Vector3 glowPosition)
{
// _selectPoof.Stop();
// _selectGlow.Stop();
//
// _selectPoof.transform.position = poofPosition;
// _selectGlow.transform.position = glowPosition;
//
// _selectPoof.Play();
// _selectGlow.Play();
}
private void HandleIsUnpressedUpdate()
{
float desiredSliderValue = GetDesiredSliderValue();
_slider.value = Mathf.MoveTowards(_slider.value, desiredSliderValue, SLIDER_SPEED * Time.deltaTime);
}
private void OnItemClick(SliderItem item)
{
PlaySelectView(item.transform.position, _handle.transform.position);
OnSelectedState?.Invoke(GetStateFromButton(item));
SetActiveItemForState(GetStateFromButton(item));
}
private void SetOnlyActiveItem(SliderItem item)
{
if (GetActiveItem() == item)
return;
if (item == null)
return;
bool previousActiveItemIsNull = !HaveActiveItem();
for (int i = 0; i < ItemsCount; i++)
GetItem(i).SetActiveState(item == GetItem(i));
_handle.SetHandleSprite(item.ActiveSprite);
if (previousActiveItemIsNull)
_slider.value = GetDesiredSliderValue();
}
private SliderItem GetActiveItem()
{
int activeItemIndex = GetActiveItemIndex();
bool isCorrectItemIndex = activeItemIndex >= 0 && activeItemIndex < ItemsCount;
return isCorrectItemIndex ? GetItem(activeItemIndex) : null;
}
private int GetActiveItemIndex()
{
for (int i = 0; i < ItemsCount; i++)
{
if (GetItem(i).IsActive)
return i;
}
return -1;
}
private bool HaveActiveItem()
{
return GetActiveItem() != null;
}
private float GetDesiredSliderValue()
{
if (!HaveActiveItem())
return _slider.value;
return GetActiveItemIndex();
}
private SliderItem GetDesiredActiveItemFromSliderValue(float sliderValue)
{
for (int i = 0; i < ItemsCount; i++)
{
GetSliderValueRangeForItemIndex(i, out float min, out float max);
if (sliderValue >= min && sliderValue <= max)
return GetItem(i);
}
return null;
}
private void GetSliderValueRangeForItemIndex(int itemIndex, out float min, out float max)
{
if (itemIndex == 0)
{
min = 0;
max = 0.5f;
}
else if (itemIndex == ItemsCount - 1)
{
min = itemIndex - 0.5f;
max = itemIndex;
}
else
{
min = itemIndex - 0.5f;
max = itemIndex + 0.5f;
}
}
private SliderItem GetButtonFromState(uint state)
{
foreach (KeyValuePair<uint, SliderItem> valuePair in _itemsDictionary)
{
if (valuePair.Key == state)
return valuePair.Value;
}
return null;
}
private uint GetStateFromButton(SliderItem item)
{
foreach (KeyValuePair<uint, SliderItem> valuePair in _itemsDictionary)
{
if (valuePair.Value == item)
return valuePair.Key;
}
return 0;
}
}