using System; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace Cryville.Crtr.Browsing { public class PVPNumber : PropertyValuePanel { double m_value; public override object Value { get { float s_value = GetDisplayValue(); return IntegerMode ? (int)s_value : (object)s_value; } set { if (value is double) m_value = (double)value; else m_value = IntegerMode ? (int)value : (double)(float)value; float s_value = GetDisplayValue(); m_text.text = s_value.ToString(); if (Range != null && MaxStep == 0) { SetRatio((float)(m_value - Range.Value.x) / (Range.Value.y - Range.Value.x)); } } } float GetDisplayValue() { double s_value = m_value; if (Precision > 0) s_value = Math.Round(s_value / Precision) * Precision; if (IntegerMode) s_value = Math.Round(s_value); return (float)s_value; } public bool IntegerMode { get; set; } public bool LogarithmicMode { get; set; } public float MaxStep { get; set; } public double Precision { get; set; } public Vector2? Range { get; set; } [SerializeField] EventTrigger m_ctn; [SerializeField] RectTransform m_handleArea; [SerializeField] RectTransform m_handle; [SerializeField] Text m_text; #pragma warning disable IDE0051 void Start() { var ev = new EventTrigger.Entry { eventID = EventTriggerType.InitializePotentialDrag }; ev.callback.AddListener(e => OnInitializePotentialDrag((PointerEventData)e)); m_ctn.triggers.Add(ev); ev = new EventTrigger.Entry { eventID = EventTriggerType.Drag }; ev.callback.AddListener(e => OnDrag((PointerEventData)e)); m_ctn.triggers.Add(ev); ev = new EventTrigger.Entry { eventID = EventTriggerType.EndDrag }; ev.callback.AddListener(e => OnEndDrag((PointerEventData)e)); m_ctn.triggers.Add(ev); ev = new EventTrigger.Entry { eventID = EventTriggerType.PointerClick }; ev.callback.AddListener(e => OnPointerClick((PointerEventData)e)); m_ctn.triggers.Add(ev); if (MaxStep != 0) SetRatio(0.5f); } void Update() { if (use && MaxStep != 0) { SetRatio(GetRatioFromPos(pp)); SetValueFromPos(pp); } } void OnRectTransformDimensionsChange() { m_handleArea.sizeDelta = new Vector2(m_handle.rect.height - m_handle.rect.width, 0); } #pragma warning restore IDE0051 Vector2 pp; bool use, nouse; public void OnInitializePotentialDrag(PointerEventData eventData) { eventData.useDragThreshold = false; pp = eventData.position; } public void OnDrag(PointerEventData eventData) { if (nouse) return; 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; if (MaxStep == 0) SetValueFromPos(eventData.position); eventData.Use(); } } public void OnEndDrag(PointerEventData eventData) { if (!nouse) { SetValueFromPos(eventData.position); Callback(Value); if (MaxStep != 0) SetRatio(0.5f); eventData.Use(); use = false; } nouse = false; } public void OnPointerClick(PointerEventData eventData) { SetValueFromPos(eventData.position); Callback(Value); eventData.Use(); } float GetRatioFromPos(Vector2 pos) { Vector2 lp; if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_handleArea, pos, null, out lp)) { lp -= m_handleArea.rect.position; return Mathf.Clamp01(lp.x / m_handleArea.rect.width); } return float.NegativeInfinity; } void SetValueFromPos(Vector2 pos) { double ratio = GetRatioFromPos(pos); double result; if (MaxStep == 0) { if (LogarithmicMode) throw new NotImplementedException(); else result = (1 - ratio) * Range.Value.x + ratio * Range.Value.y; } else { double delta = (ratio - 0.5f) * 2 * MaxStep * Time.deltaTime; if (LogarithmicMode) result = Math.Pow(Math.E, Math.Log(m_value) + delta); else result = m_value + delta; } if (Range != null) { if (result < Range.Value.x) result = Range.Value.x; else if (result > Range.Value.y) result = Range.Value.y; } Value = result; } void SetRatio(float ratio) { m_handle.anchorMin = new Vector2(ratio, m_handle.anchorMin.y); m_handle.anchorMax = new Vector2(ratio, m_handle.anchorMax.y); } } }