- Home /
The question is answered, right answer was accepted
PropertyDrawer gives strange results about the position and width of rect.
I cannot understand why this PropertyDrawer gives strange results about the position and width of rect.
[CustomPropertyDrawer(typeof(MinMaxSliderAttribute))]
public class MinMaxSliderPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
MinMaxSliderAttribute minMaxSliderAttribute = (MinMaxSliderAttribute)attribute;
if (property.propertyType == SerializedPropertyType.Vector2)
{
// Draw the label
Rect controlRect = EditorGUI.PrefixLabel(position, label);
float sliderPadding = 5f;
float floatFieldWidth = EditorGUIUtility.fieldWidth;
float sliderWidth = controlRect.width - 2f * (floatFieldWidth + sliderPadding);
Rect minFloatFieldRect = new Rect(
controlRect.x,
controlRect.y,
floatFieldWidth,
controlRect.height);
Rect sliderRect = new Rect(
controlRect.x + floatFieldWidth + sliderPadding,
controlRect.y,
sliderWidth,
controlRect.height);
Rect maxFloatFieldRect = new Rect(
controlRect.x + floatFieldWidth + sliderWidth + 2f * sliderPadding,
controlRect.y,
floatFieldWidth,
controlRect.height);
// Draw the slider
EditorGUI.BeginChangeCheck();
Vector2 sliderValue = property.vector2Value;
EditorGUI.MinMaxSlider(sliderRect, ref sliderValue.x, ref sliderValue.y, minMaxSliderAttribute.MinValue, minMaxSliderAttribute.MaxValue);
sliderValue.x = EditorGUI.FloatField(minFloatFieldRect, sliderValue.x);
sliderValue.x = Mathf.Clamp(sliderValue.x, minMaxSliderAttribute.MinValue, Mathf.Min(minMaxSliderAttribute.MaxValue, sliderValue.y));
sliderValue.y = EditorGUI.FloatField(maxFloatFieldRect, sliderValue.y);
sliderValue.y = Mathf.Clamp(sliderValue.y, Mathf.Max(minMaxSliderAttribute.MinValue, sliderValue.x), minMaxSliderAttribute.MaxValue);
if (EditorGUI.EndChangeCheck())
{
property.vector2Value = sliderValue;
}
}
else
{
base.OnGUI(position, property, label);
}
}
}
And after I add an offset range of 30f. Everything looks good.
[CustomPropertyDrawer(typeof(MinMaxSliderAttribute))]
public class MinMaxSliderPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
MinMaxSliderAttribute minMaxSliderAttribute = (MinMaxSliderAttribute)attribute;
if (property.propertyType == SerializedPropertyType.Vector2)
{
// Draw the label
Rect controlRect = EditorGUI.PrefixLabel(position, label);
controlRect.x -= 30f;
float sliderPadding = 5f;
float floatFieldWidth = EditorGUIUtility.fieldWidth + 30f;
float sliderWidth = controlRect.width - 2f * (floatFieldWidth + sliderPadding) + 90f;
Rect minFloatFieldRect = new Rect(
controlRect.x,
controlRect.y,
floatFieldWidth,
controlRect.height);
Rect sliderRect = new Rect(
controlRect.x + floatFieldWidth + sliderPadding - 30f,
controlRect.y,
sliderWidth,
controlRect.height);
Rect maxFloatFieldRect = new Rect(
controlRect.x + floatFieldWidth + sliderWidth + 2f * sliderPadding - 60f,
controlRect.y,
floatFieldWidth,
controlRect.height);
// Draw the slider
EditorGUI.BeginChangeCheck();
Vector2 sliderValue = property.vector2Value;
EditorGUI.MinMaxSlider(sliderRect, ref sliderValue.x, ref sliderValue.y, minMaxSliderAttribute.MinValue, minMaxSliderAttribute.MaxValue);
sliderValue.x = EditorGUI.FloatField(minFloatFieldRect, sliderValue.x);
sliderValue.x = Mathf.Clamp(sliderValue.x, minMaxSliderAttribute.MinValue, Mathf.Min(minMaxSliderAttribute.MaxValue, sliderValue.y));
sliderValue.y = EditorGUI.FloatField(maxFloatFieldRect, sliderValue.y);
sliderValue.y = Mathf.Clamp(sliderValue.y, Mathf.Max(minMaxSliderAttribute.MinValue, sliderValue.x), minMaxSliderAttribute.MaxValue);
if (EditorGUI.EndChangeCheck())
{
property.vector2Value = sliderValue;
}
}
else
{
base.OnGUI(position, property, label);
}
}
}
Can you tell me where I was wrong?
The default layouts get scrunched up sometimes, usually it's good to draw labels separately, or reduce the size of labels.
When I reduce the width of the label, my label is missing, while the other labels drawn by Unity are still displayed even if it has the same amount of text. I noticed there was a 30f space between the label and the rest. However, that still cannot explain why the FloatFields are shorter than normal (Debug produces a result of 50).
Answer by Bunny83 · Feb 21, 2019 at 03:18 PM
I guess this is related to the indent of the nested elements. For example the PrefixLabel method will add EditorGUI.indent
to the x position. However the returned rect will always start at the same position.
Note that EditorGUI.indent
is just a property which returns EditorGUI.indentLevel * 15f. The indentLevel is increased by the any code that displays nested elements. Most controls will use the indent level as well. The FloatField for example uses this internally:
return EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor, EditorGUI.IndentedRect(position), new Rect(0f, 0f, 0f, 0f), controlID, value, EditorGUI.kFloatFieldFormatString, style, false);
Note that the IndentedRect method just does add the indent value to the x value and subract it from the width:
public static Rect IndentedRect(Rect source)
{
float indent = EditorGUI.indent;
return new Rect(source.x + indent, source.y, source.width - indent, source.height);
}
The FloatField that takes also a label does the splitting beforehand and calls the internal "DoFloatField" without the indent but with the calculated content rect.
The only proper way I know to "remove" any indent is to save the old indentLevel value in a local variable, set the indentLevel to 0, draw your content and restore the indentLevel to the old value.
So each rect has been indented 2 levels, and only label is what I want. Thanks for your answer.