If anyone ever needs to create a vertical range slider which works inside of EditorWindow, here it is:
//invoke from inside OnGUI of EditorWindow
// Igor Aherne 14 May 2017
// facebook.com/igor.aherne
void drawVerticalRangeSlider(Rect rectangle,
Color barColor,
Color handlesColor,
ref float currMin,
ref float currMax,
Vector2 minMax,
float barWidthCoeff = 0.2f,
float handlesSizeCoeff = 0.7f) {
//determine the percentage ratios (0.0 to 1.0f) where the current minmax values are sitting:
float minMax_difference = (minMax.y - minMax.x);
float currMin_pcnt = currMin / minMax_difference; //some value (for example 0.3)
float currMax_pcnt = currMax / minMax_difference; //for example (0.7)
//"vertical line" rectangle:
Rect barRect = rectangle;
barRect.width = rectangle.width * barWidthCoeff; //narrow it down a little
barRect.center = rectangle.center;
EditorGUI.DrawRect(barRect, barColor);
Rect lowerHandleRect = rectangle;
lowerHandleRect.width *= handlesSizeCoeff;
lowerHandleRect.height = lowerHandleRect.width;//make it square.
//draw the min-handle:
lowerHandleRect.center = new Vector2( barRect.center.x,
barRect.yMin + barRect.height*(1 - currMin_pcnt) + lowerHandleRect.height*0.5f);
//notice, we added handle's height since we want its top center to act as "pivot". We added and didn't subtract
//because the GUI has height inverted.
//keep in mind the gui has y-axis inverted:
Rect upperHandleRect = lowerHandleRect;
upperHandleRect.center = new Vector2( barRect.center.x,
barRect.yMin + barRect.height*(1 - currMax_pcnt) - upperHandleRect.height*0.5f);
#region event processing
Event e_current = Event.current;
int lowerHandleID = GUIUtility.GetControlID(FocusType.Passive);
int upperHandleID = GUIUtility.GetControlID(FocusType.Passive);
switch (e_current.type) {
case EventType.MouseDown: {
if (lowerHandleRect.Contains(e_current.mousePosition)) {
GUIUtility.hotControl = lowerHandleID;
} else if(upperHandleRect.Contains(e_current.mousePosition)){
GUIUtility.hotControl = upperHandleID;
}
}break;
case EventType.MouseDrag: {
//we will first check how much the sliders would move, then then check if they should move
float value_deltaChange = (e_current.delta.y / barRect.height);
//now let's check if the change is applicable
if(GUIUtility.hotControl == lowerHandleID) {
// modify our reference min-float. Recall that we will scale this percentage change
// by the possible totalRange of our slider. We calmp, to forbit the value getting outside
// of that range.
currMin -= value_deltaChange * minMax_difference;//notice, minus - GUI is inverted in height
currMin = Mathf.Clamp(currMin, minMax.x, currMax);
e_current.Use();
}
else if(GUIUtility.hotControl == upperHandleID) {
currMax -= value_deltaChange * minMax_difference;//notice, minus
currMax = Mathf.Clamp(currMax, currMin, minMax.y);
e_current.Use();
}
Repaint();
}break;
case EventType.Repaint:{
Rect fillerRect = barRect;
fillerRect.width = barRect.width * 1.4f;
fillerRect.center = barRect.center; //re-center after changing width
//strectch to fit corners of handles
fillerRect.yMin = upperHandleRect.yMax;
fillerRect.yMax = lowerHandleRect.yMin;
Color fillerCollor = new Color( handlesColor.r * 0.4f,
handlesColor.g * 0.4f,
handlesColor.b * 0.4f,
handlesColor.a);
EditorGUI.DrawRect(fillerRect, fillerCollor);
//draw the lower handle:
EditorGUI.DrawRect(lowerHandleRect, handlesColor);
//upper handle:
handlesColor.r *= 0.8f;
handlesColor.g *= 0.8f;
handlesColor.b *= 0.8f;
EditorGUI.DrawRect(upperHandleRect, handlesColor);
}break;
}//end swtich event-type
#endregion
}