I made some custom control named Range Control in Unity. It has two buttons a "plus" and a "minus" and an input field that shows the current value. The control has (for now) two implementations:
- None-List - The value is clamped between a min and a max.
- Using a List - The control accepts a range (list) of values and changing the index (much like a dropdown).
Both implementation has almost identical UI (on the 2nd one the input field is read only cause you get a range from the outside).
I want to make one control of the two. One prefab with one script and let the user decide if it will work like #1 or #2 (or #3 if the future holds).
This is what I have by now. How can I make it better?
public class RangeControlBase : MonoBehaviour
{
public InputField NumberInputfield;
public string m_sPrefix;
public string m_sSuffix;
public RangeControlType RangeType;
public Button PlusButton;
public Button MinusButton;
void Awake()
{
PlusButton.onClick.AddListener(() => ChangeValue(1));
MinusButton.onClick.AddListener(() => ChangeValue(-1));
}
public string Prefix
{
get
{
return m_sPrefix;
}
set
{
m_sPrefix = value;
UpdateValue();
}
}
public string Suffix
{
get
{
return m_sSuffix;
}
set
{
m_sSuffix = value;
UpdateValue();
}
}
public virtual void ChangeValue(int direction)
{
throw new NotImplementedException();
}
public virtual void UpdateValue()
{
throw new NotImplementedException();
}
}
Range Control:
public class RangeControl : RangeControlBase
{
public float Stepping = 5;
float m_fMinRange = 10;
float m_fMaxRange = 1000;
float m_fValue;
public Action<float> OnValueChanged = delegate { };
void Start()
{
NumberInputfield.onEndEdit.AddListener(t => SetStringValue(t));
}
public void SetStringValue(string text)
{
float value;
text = Regex.Replace(text, string.Format(@"\({0}|{1}\)", Prefix, Suffix), string.Empty);
if (float.TryParse(text, out value))
{
Value = value;
}
}
public float Value
{
get { return m_fValue; }
set
{
m_fValue = value;
UpdateValue();
}
}
public float MinRange
{
get { return m_fMinRange; }
set
{
m_fMinRange = value;
UpdateValue();
}
}
public float MaxRange
{
get { return m_fMaxRange; }
set
{
m_fMaxRange = value;
UpdateValue();
}
}
public override void ChangeValue(int direction)
{
Value += direction * Stepping;
}
public override void UpdateValue()
{
m_fValue = Mathf.Clamp(Value, MinRange, MaxRange);
NumberInputfield.text = string.Format("{0}{1}{2}", Prefix, m_fValue, Suffix);
MinusButton.interactable = m_fValue != m_fMinRange;
PlusButton.interactable = m_fValue != m_fMaxRange;
OnValueChanged(m_fValue);
}
}
List Range Control:
public class ListRangeControl : RangeControlBase
{
public Action<int> OnSelectedIndexChanged = delegate { };
public Action<float> OnValueChanged = delegate { };
List<float> m_itemsList;
int m_iIndex = -1;
public List<float> ItemsList
{
get
{
return m_itemsList;
}
set
{
m_itemsList = value;
m_iIndex = 0;
UpdateValue();
}
}
public int Index
{
set
{
m_iIndex = value;
UpdateValue();
}
}
public override void ChangeValue(int direction)
{
m_iIndex += direction;
OnSelectedIndexChanged(m_iIndex);
UpdateValue();
}
public override void UpdateValue()
{
if (m_iIndex < 0 || m_iIndex > m_itemsList.Count)
{
return;
}
float value = m_itemsList[m_iIndex];
NumberInputfield.text = string.Format("{0}{1}{2}", Prefix, value, Suffix);
MinusButton.interactable = m_iIndex > 0;
PlusButton.interactable = m_iIndex < m_itemsList.Count - 1;
OnValueChanged(value);
}
}
Test Script:
public class TestRangeControls : MonoBehaviour
{
public RangeControl RangeControl;
public ListRangeControl ListRange;
void Start()
{
//Set Range Control
RangeControl.OnValueChanged += v => { Debug.Log("Selected value is: " + v); };
RangeControl.MinRange = 200;
RangeControl.MaxRange = 2000;
RangeControl.Stepping = 50;
RangeControl.Value = Mathf.RoundToInt(Random.Range(RangeControl.MinRange, RangeControl.MaxRange));
//Set List Range Control
ListRange.OnSelectedIndexChanged += i => { Debug.Log("Selected index is: " + i); };
List<float> numList = new List<float>();
for (int i = 1; i < 11; i++)
{
numList.Add(i * 100);
}
ListRange.ItemsList = numList;
ListRange.Index = Random.Range(1, 11);
}
}