392 lines
12 KiB
C#
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;
|
|||
|
}
|
|||
|
}
|