- Home /
Dual Slider / Min Max Slider for GUI
I need this:
http://docs.unity3d.com/Documentation/ScriptReference/EditorGUI.MinMaxSlider.html
but in a GUI element. I can't seem to find any info on if one exists or how to go about creating something like this. Just need a slider that would have both a min and a max value.
Answer by numberkruncher · Aug 12, 2013 at 10:01 PM
As you have found, this is an editor-only control which unfortunately does not have a runtime counterpart.
You could define your own by obtaining a unique ID for your control and then monitoring its events accordingly. You would need to define several suitable GUIStyle
's, however to get started you could just make use of the provided ones.
I have thrown something together for you, but please bare in mind that this has not been properly tested.
Hopefully this will at least serve as a starting point for you:
Usage example:
public class TestSlider : MonoBehaviour {
public float minValue = -10;
public float maxValue = 10;
private void OnGUI() {
GUILayout.BeginArea(new Rect(100, 100, 300, 300));
MyGUI.MinMaxSlider(ref minValue, ref maxValue, -20, 20);
GUILayout.EndArea();
}
}
Implementation:
using UnityEngine;
public static class MyGUI {
#region Implementation
private static GUIStyle backgroundStyle = "Box";
private static GUIStyle thumbStyle = "Box";
private static GUIStyle minThumbStyle = "Button";
private static GUIStyle maxThumbStyle = "Button";
private static void DoMinMaxSlider(Rect position, ref float minValue, ref float maxValue, float minLimit, float maxLimit) {
int controlID = GUIUtility.GetControlID(FocusType.Passive);
int minThumbControlID = GUIUtility.GetControlID(FocusType.Passive);
int maxThumbControlID = GUIUtility.GetControlID(FocusType.Passive);
// Do not proceed for layout event.
if (Event.current.type == EventType.Layout)
return;
// Clamp current state of values.
minValue = Mathf.Clamp(minValue, minLimit, maxLimit);
maxValue = Mathf.Max(minValue, Mathf.Clamp(maxValue, minLimit, maxLimit));
// Calculate normalized version of values.
float range = Mathf.Abs(maxLimit - minLimit);
float normalizedMinValue = (minValue - minLimit) / range;
float normalizedMaxValue = (maxValue - minLimit) / range;
// Calculate visual version of values.
float minValueX = position.x + normalizedMinValue * position.width;
float maxValueX = position.x + normalizedMaxValue * position.width;
Rect minThumbPosition = new Rect(minValueX - 7, position.y, 7, position.height);
Rect maxThumbPosition = new Rect(maxValueX, position.y, 7, position.height);
float normalizedMousePosition;
switch (Event.current.GetTypeForControl(controlID)) {
case EventType.MouseDown:
// Mouse pressed down on minimum thumb position?
if (minThumbPosition.Contains(Event.current.mousePosition)) {
GUIUtility.hotControl = minThumbControlID;
Event.current.Use();
}
// Mouse pressed down on maximum thumb position?
else if (maxThumbPosition.Contains(Event.current.mousePosition)) {
GUIUtility.hotControl = maxThumbControlID;
Event.current.Use();
}
break;
case EventType.MouseUp:
// Extremely important!!
if (GUIUtility.hotControl == minThumbControlID || GUIUtility.hotControl == maxThumbControlID || GUIUtility.hotControl == controlID)
GUIUtility.hotControl = 0;
break;
case EventType.MouseDrag:
normalizedMousePosition = (Event.current.mousePosition.x - position.x) / position.width;
// Process mouse movement?
if (GUIUtility.hotControl == minThumbControlID) {
float newMinValue = Mathf.Clamp(normalizedMousePosition * range + minLimit, minLimit, maxValue);
if (newMinValue != minValue) {
minValue = newMinValue;
GUI.changed = true;
}
Event.current.Use();
}
else if (GUIUtility.hotControl == maxThumbControlID) {
float newMaxValue = Mathf.Clamp(normalizedMousePosition * range + minLimit, minValue, maxLimit);
if (newMaxValue != maxValue) {
maxValue = newMaxValue;
GUI.changed = true;
}
Event.current.Use();
}
break;
case EventType.Repaint:
// Draw background of slider control.
backgroundStyle.Draw(new Rect(position.x, position.y + 5, position.width, position.height - 10), GUIContent.none, controlID);
// Draw background of thumb range.
thumbStyle.Draw(new Rect(minValueX, position.y + 9, maxValueX - minValueX, 5), GUIContent.none, false, false, false, false);
// Draw minimum thumb button.
minThumbStyle.Draw(minThumbPosition, GUIContent.none, minThumbControlID);
// Draw maximum thumb button.
maxThumbStyle.Draw(maxThumbPosition, GUIContent.none, maxThumbControlID);
break;
}
}
#endregion
#region Absolute Version
public static void MinMaxSlider(Rect position, ref float minValue, ref float maxValue, float minLimit, float maxLimit) {
DoMinMaxSlider(position, ref minValue, ref maxValue, minLimit, maxLimit);
}
#endregion
#region Layout-enabled Version
public static void MinMaxSlider(ref float minValue, ref float maxValue, float minLimit, float maxLimit) {
Rect position = GUILayoutUtility.GetRect(GUIContent.none, backgroundStyle);
DoMinMaxSlider(position, ref minValue, ref maxValue, minLimit, maxLimit);
}
#endregion
}
Just a comment for anyone reading this in the future. Though this code does work quite well, it is extremely heavy on CPU (47% load at all times from the Repaint event). I will be re-writing this to ins$$anonymous$$d use game objects in the scene with a secondary camera for GUI elements. Still a great resource though :)
@h8crew Did you ever re-write this using game objects?
Answer by ZenithCode · Aug 12, 2013 at 08:56 PM
There you go:
http://docs.unity3d.com/Documentation/ScriptReference/GUI.HorizontalSlider.html http://docs.unity3d.com/Documentation/ScriptReference/GUI.VerticalSlider.html
Unfortunately these controls do not have the dual slider mechanism which was requested in the question. See my answer for example implementation of such a control.
Your answer
Follow this Question
Related Questions
Minmax slider on Unity 4.6? 3 Answers
[4.6 GUI] Displaying my pause menu when ESC is pressed 2 Answers
GUI 2D Bounding Box 1 Answer
Making iTween work with OnGUI functions 3 Answers