Files
crtr/Assets/Cryville/Crtr/Config/UI/PVPNumberBase.cs

131 lines
3.3 KiB
C#

using System;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace Cryville.Crtr.Config.UI {
public abstract class PVPNumberBase : PropertyValuePanel, IInitializePotentialDragHandler, IDragHandler, IEndDragHandler, IPointerClickHandler {
[SerializeField]
RectTransform m_handleArea;
[SerializeField]
Image m_handle;
[SerializeField]
TMP_InputField m_text;
protected void Start() {
m_text.interactable = SetMapped;
m_text.onValueChanged.AddListener(OnTextEdited);
m_text.onDeselect.AddListener(OnTextDeselected);
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();
}
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() { }
protected virtual void Update() {
if (use) {
SetRatio(GetRatioFromPos(pp));
SetValueFromPos(pp);
}
}
Camera cam;
Vector2 pp;
bool use, nouse;
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);
OnIdle();
eventData.Use();
use = false;
}
nouse = false;
}
public void OnPointerClick(PointerEventData eventData) {
SetValueFromPos(eventData.position);
eventData.Use();
}
float GetRatioFromPos(Vector2 pos) {
Vector2 lp;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_handleArea, pos, cam, out lp)) {
lp -= m_handleArea.rect.position;
return Mathf.Clamp01(lp.x / m_handleArea.rect.width);
}
return float.NegativeInfinity;
}
void SetValueFromPos(Vector2 pos) {
double min = double.NegativeInfinity, max = double.PositiveInfinity;
if (Range != null && Range.Length == 2) {
min = (double)Range[0];
max = (double)Range[1];
}
double ratio = GetRatioFromPos(pos);
double result = GetValue(ratio, Time.deltaTime, min, max);
if (result < min) result = min;
else if (result > max) result = max;
RawValue = result;
}
protected abstract double GetValue(double ratio, float deltaTime, double min, double max);
protected void SetRatio(float ratio) {
m_handle.rectTransform.anchorMin = new Vector2(ratio, m_handle.rectTransform.anchorMin.y);
m_handle.rectTransform.anchorMax = new Vector2(ratio, m_handle.rectTransform.anchorMax.y);
m_handle.rectTransform.anchoredPosition = Vector2.zero;
}
}
}