Skip to content

Instantly share code, notes, and snippets.

@yagero
Last active February 16, 2021 19:50
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save yagero/0a3812498bee0438541d64c8665c6076 to your computer and use it in GitHub Desktop.
Save yagero/0a3812498bee0438541d64c8665c6076 to your computer and use it in GitHub Desktop.
EditorGUILayout Fields which properly handles multi-object editing
using System;
using UnityEngine;
using UnityEditor;
public static class EditorGUILayoutExtensions
{
/// <summary>
/// Add a EditorGUILayout.ToggleLeft which properly handles multi-object editing
/// </summary>
public static void ToggleLeft(this SerializedProperty prop, GUIContent label, params GUILayoutOption[] options)
{
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = prop.hasMultipleDifferentValues;
var newValue = EditorGUILayout.ToggleLeft(label, prop.boolValue, options);
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck())
prop.boolValue = newValue;
}
/// <summary>
/// Create a EditorGUILayout.Slider which properly handles multi-object editing
/// We apply the 'convIn' conversion to the SerializedProperty value before exposing it as a Slider.
/// We apply the 'convOut' conversion to the Slider value to store it back to the SerializedProperty.
/// </summary>
/// <param name="prop">The value the slider shows. This determines the position of the draggable thumb.</param>
/// <param name="label">Label in front of the slider.</param>
/// <param name="leftValue">The value at the left end of the slider.</param>
/// <param name="rightValue">The value at the right end of the slider.</param>
/// <param name="convIn">Conversion function applied on the SerializedProperty to get the Slider value</param>
/// <param name="convOut">Conversion function applied on the Slider value to get the SerializedProperty</param>
public static void FloatSlider(
this SerializedProperty prop,
GUIContent label,
float leftValue, float rightValue,
Func<float, float> convIn,
Func<float, float> convOut,
params GUILayoutOption[] options)
{
var floatValue = convIn(prop.floatValue);
EditorGUI.BeginChangeCheck();
{
EditorGUI.showMixedValue = prop.hasMultipleDifferentValues;
{
floatValue = EditorGUILayout.Slider(label, floatValue, leftValue, rightValue, options);
}
EditorGUI.showMixedValue = false;
}
if (EditorGUI.EndChangeCheck())
prop.floatValue = convOut(floatValue);
}
}
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(UsageExample))]
[CanEditMultipleObjects]
public class UsageExampleEditor : Editor
{
SerializedProperty propBool;
SerializedProperty propFloat;
void OnEnable()
{
propBool = serializedObject.FindProperty("MyBoolProp");
propFloat = serializedObject.FindProperty("MyFloatProp");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
///////////////////////////////////////////////
// HOW TO PROPERLY EXPOSE A TOGGLE LEFT
///////////////////////////////////////////////
// /!\ THIS CODE DOESN'T PROPERLY HANDLE MULTI-OBJECT EDITING /!\
propBool.boolValue = EditorGUILayout.ToggleLeft("My Bool", propBool.boolValue);
// THIS IS HOW YOU PROPERLY HANDLE MULTI-OBJECT EDITING
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = propBool.hasMultipleDifferentValues;
var newValue = EditorGUILayout.ToggleLeft("My Bool", propBool.boolValue);
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck())
propBool.boolValue = newValue;
// OR USE THIS EXTENSION METHOD
propBool.ToggleLeft(new GUIContent("My Bool"));
//////////////////////////////////////////////////////////////
// HOW TO PROPERLY EXPOSE A FLOAT SLIDER WITH SOME CONVERSION
// for example we want to expose 1/value as a slider
//////////////////////////////////////////////////////////////
// /!\ THIS CODE DOESN'T PROPERLY HANDLE MULTI-OBJECT EDITING /!\
var exposedFloatValue = 1f / propFloat.floatValue;
exposedFloatValue = EditorGUILayout.Slider("My Float", exposedFloatValue, 0.1f, 1.0f);
propFloat.floatValue = 1f / exposedFloatValue;
// USE THIS NICE EXTENSION METHOD INSTEAD :)
propFloat.FloatSlider(
new GUIContent("My Float"),
0.1f, 1.0f,
(v) => 1f / v, // conversion SerializedProperty => Slider
(v) => 1f / v); // conversion Slider => SerializedProperty
serializedObject.ApplyModifiedProperties();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment