using System;
using BepInEx;
using CharaCustom;
using KKAPI.Utilities;
using UniRx;
using UniRx.Triggers;
using UnityEngine;
using UnityEngine.UI;
using Object = UnityEngine.Object;
namespace KKAPI.Maker.UI
{
///
/// Custom control that draws a slider and a text box (both are used to edit the same value)
///
public class MakerSlider : BaseEditableGuiEntry
{
private static Transform _sliderCopy;
private readonly string _settingName;
private readonly float _maxValue;
private readonly float _minValue;
private readonly float _defaultValue;
///
/// Create a new custom control. Create and register it in .
///
/// Text displayed next to the slider
/// Category the control will be created under
/// Plugin that owns the control
/// Lowest allowed value (inclusive)
/// Highest allowed value (inclusive)
/// Value the slider will be set to after creation
public MakerSlider(MakerCategory category, string settingName, float minValue, float maxValue, float defaultValue, BaseUnityPlugin owner) : base(category, defaultValue, owner)
{
_settingName = settingName;
_minValue = minValue;
_maxValue = maxValue;
_defaultValue = defaultValue;
}
///
/// Custom converter from text in the textbox to the slider value.
/// If not set, float.Parse(txt) / 100f
is used.
///
public Func StringToValue { get; set; }
///
/// Custom converter from the slider value to what's displayed in the textbox.
/// If not set, Mathf.RoundToInt(f * 100).ToString()
is used.
///
public Func ValueToString { get; set; }
private static Transform SliderCopy
{
get
{
if (_sliderCopy == null)
MakeCopy();
return _sliderCopy;
}
}
private static void MakeCopy()
{
var originalSlider = GameObject.FindObjectOfType().transform;
_sliderCopy = Object.Instantiate(originalSlider, GuiCacheTransfrom, false);
_sliderCopy.gameObject.SetActive(false);
_sliderCopy.name = "sldTemp";
var slider = _sliderCopy.GetComponent();
slider.onChange = null;
slider.onPointerUp = null;
slider.onSetDefaultValue = null;
foreach (var renderer in _sliderCopy.GetComponentsInChildren())
renderer.raycastTarget = true;
RemoveLocalisation(_sliderCopy.gameObject);
}
///
protected internal override void Initialize()
{
if (_sliderCopy == null)
MakeCopy();
}
///
protected override GameObject OnCreateControl(Transform subCategoryList)
{
var tr = Object.Instantiate(SliderCopy, subCategoryList, false);
tr.name = "SliderSet";
var sliderSet = tr.GetComponent();
sliderSet.onChange = null;
sliderSet.onPointerUp = null;
sliderSet.onSetDefaultValue = null;
GameObject.Destroy(sliderSet);
sliderSet.title.text = _settingName;
sliderSet.title.color = TextColor;
SetTextAutosize(sliderSet.title);
var slider = sliderSet.slider;
slider.minValue = _minValue;
slider.maxValue = _maxValue;
slider.onValueChanged.ActuallyRemoveAllListeners();
slider.onValueChanged.AddListener(SetValue);
slider.GetComponent()
.OnScrollAsObservable()
.Subscribe(
data =>
{
var scrollDelta = data.scrollDelta.y;
var valueChange = Mathf.Pow(10, Mathf.Round(Mathf.Log10(slider.maxValue / 100)));
if (scrollDelta < 0f)
slider.value += valueChange;
else if (scrollDelta > 0f)
slider.value -= valueChange;
});
var inputField = sliderSet.input;
inputField.onEndEdit.AddListener(
txt =>
{
try
{
var result = StringToValue?.Invoke(txt) ?? float.Parse(txt) / 100f;
slider.value = Mathf.Clamp(result, slider.minValue, slider.maxValue);
}
catch
{
// Ignore parsing errors, lets user keep typing
}
});
slider.onValueChanged.AddListener(
f =>
{
if (ValueToString != null)
inputField.text = ValueToString(f);
else
inputField.text = Mathf.RoundToInt(f * 100).ToString();
});
var resetButton = sliderSet.button;
resetButton.onClick.ActuallyRemoveAllListeners();
resetButton.onClick.AddListener(() => slider.value = _defaultValue);
BufferedValueChanged.Subscribe(f => slider.value = f);
return tr.gameObject;
}
}
}