using System; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace Cryville.Crtr.Config.UI { public abstract class PVPNumberBase : PropertyValuePanel { [SerializeField] GameObject m_slider; [SerializeField] RectTransform m_handleArea; [SerializeField] Image m_handle; [SerializeField] TMP_InputField m_text; [SerializeField] Button m_textActivationButton; protected void Start() { m_slider.AddComponent().parent = this; m_text.interactable = SetMapped; m_text.onValueChanged.AddListener(OnTextEdited); m_text.onDeselect.AddListener(OnTextDeselected); m_textActivationButton.interactable = SetMapped; OnIdle(); } void OnTextEdited(string value) { if (!m_text.isFocused) return; if (double.TryParse(value, out var result)) { try { MappedValue = result; } catch (Exception) { } } } void OnTextDeselected(string value) { OnValueUpdated(); m_text.enabled = false; } protected override void OnValueUpdated() { if (Range != null && Range.Length == 2) { var min = (double)Range[0]; var max = (double)Range[1]; var value = Convert.ToDouble(RawValue); if (value < min) { value = min; RawValue = value; } else if (value > max) { value = max; RawValue = value; } } if (!m_text.isFocused) { m_text.text = MappedValue.ToString(); } } protected virtual void OnIdle() { } class SliderBehaviour : UIBehaviour, IInitializePotentialDragHandler, IDragHandler, IEndDragHandler, IPointerClickHandler { public PVPNumberBase parent; Camera cam; Vector2 pp; bool use, nouse; void Update() { if (use) { parent.SetRatio(GetRatioFromPos(pp)); SetValueFromPos(pp); } } public void OnInitializePotentialDrag(PointerEventData eventData) { // eventData.useDragThreshold = false; pp = eventData.position; } public void OnDrag(PointerEventData eventData) { if (nouse) return; cam = eventData.pressEventCamera; if (!use) { var delta = eventData.position - pp; float dx = Mathf.Abs(delta.x), dy = Mathf.Abs(delta.y); if (dx > dy) use = true; else if (dx < dy) nouse = true; } if (use) { pp = eventData.position; eventData.Use(); } } public void OnEndDrag(PointerEventData eventData) { if (!nouse) { SetValueFromPos(eventData.position); parent.OnIdle(); eventData.Use(); use = false; } nouse = false; } public void OnPointerClick(PointerEventData eventData) { SetValueFromPos(eventData.position); eventData.Use(); } float GetRatioFromPos(Vector2 pos) { RectTransform handleArea = parent.m_handleArea; if (RectTransformUtility.ScreenPointToLocalPointInRectangle(handleArea, pos, cam, out Vector2 lp)) { lp -= handleArea.rect.position; return Mathf.Clamp01(lp.x / handleArea.rect.width); } return float.NegativeInfinity; } void SetValueFromPos(Vector2 pos) { parent.GetRange(out double min, out double max); double ratio = GetRatioFromPos(pos); double result = parent.GetValue(ratio, Time.deltaTime, min, max); if (result < min) result = min; else if (result > max) result = max; parent.RawValue = result; } } void GetRange(out double min, out double max) { min = double.NegativeInfinity; max = double.PositiveInfinity; if (Range != null && Range.Length == 2) { min = (double)Range[0]; max = (double)Range[1]; } } protected void SetRatio(float ratio) { RectTransform handle = m_handle.rectTransform; handle.anchorMin = new Vector2(ratio, handle.anchorMin.y); handle.anchorMax = new Vector2(ratio, handle.anchorMax.y); handle.anchoredPosition = Vector2.zero; } protected abstract double GetValue(double ratio, float deltaTime, double min, double max); } }