Created
April 9, 2021 01:37
-
-
Save acoppes/d3e513f5e38b9db41303728c90404ebe to your computer and use it in GitHub Desktop.
Just a Untiy prop drawer for optonal fields
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using UnityEditor; | |
using UnityEngine; | |
namespace Gemserk.Utils | |
{ | |
[CustomPropertyDrawer(typeof(OptionalFieldsAttribute))] | |
public class OptionalFieldsPropertyDrawer : PropertyDrawer | |
{ | |
private float propertyFieldHeight = 20; | |
private struct FieldTuple | |
{ | |
public string checkPropertyName; | |
public string fieldPropertyName; | |
} | |
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) | |
{ | |
EditorGUI.BeginProperty(position, label, property); | |
var r1 = new Rect(position.x, position.y, position.width, propertyFieldHeight); | |
// Draw label | |
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label); | |
// Don't make child fields be indented | |
var indent = EditorGUI.indentLevel; | |
EditorGUI.indentLevel = 1; | |
var showNext = false; | |
var lastCheckPropertyName = string.Empty; | |
var enabledProperties = new List<FieldTuple>(); | |
var disabledProperties = new List<FieldTuple> { | |
new FieldTuple | |
{ | |
checkPropertyName = string.Empty, | |
fieldPropertyName = "Click to add", | |
} | |
}; | |
var nextElement = property.Copy(); | |
var hasElement = nextElement.Next(true); | |
while (hasElement) | |
{ | |
// var prop = iterator.Current as SerializedProperty; | |
var prop = nextElement; | |
if (prop.name.ToLowerInvariant().StartsWith("check")) | |
{ | |
showNext = prop.boolValue; | |
lastCheckPropertyName = prop.name; | |
hasElement = nextElement.Next(false); | |
continue; | |
} | |
if (!showNext) | |
{ | |
if (lastCheckPropertyName != null) | |
{ | |
disabledProperties.Add(new FieldTuple | |
{ | |
checkPropertyName = lastCheckPropertyName, | |
fieldPropertyName = prop.name | |
}); | |
} | |
lastCheckPropertyName = null; | |
hasElement = nextElement.Next(false); | |
continue; | |
} | |
if (showNext) | |
{ | |
if (lastCheckPropertyName != null) | |
{ | |
enabledProperties.Add(new FieldTuple | |
{ | |
checkPropertyName = lastCheckPropertyName, | |
fieldPropertyName = prop.name | |
}); | |
} | |
lastCheckPropertyName = null; | |
} | |
hasElement = nextElement.Next(false); | |
} | |
r1.y += propertyFieldHeight; | |
EditorGUI.BeginChangeCheck(); | |
var options = disabledProperties.Select(t => t.fieldPropertyName).ToArray(); | |
if (options.Length > 1) | |
{ | |
var newSelectedIndex = EditorGUI.Popup(r1, 0, options); | |
if (EditorGUI.EndChangeCheck()) | |
{ | |
// add property to enable list by checking bool... | |
// reset options | |
if (newSelectedIndex > 0) | |
{ | |
var tuple = disabledProperties[newSelectedIndex]; | |
var checkProperty = property.FindPropertyRelative(tuple.checkPropertyName); | |
checkProperty.boolValue = true; | |
} | |
} | |
r1.y += propertyFieldHeight; | |
} | |
else | |
{ | |
EditorGUI.Popup(r1, 0, new []{ "Nothing to add" }); | |
r1.y += propertyFieldHeight; | |
} | |
foreach (var tuple in enabledProperties) | |
{ | |
// // Draw fields - passs GUIContent.none to each so they are drawn without labels | |
var prop = property.FindPropertyRelative(tuple.fieldPropertyName); | |
if (prop == null) | |
continue; | |
var propRect = r1; | |
var checkRect = r1; | |
propRect.width -= 40; | |
checkRect.x = checkRect.width - 30; | |
checkRect.width = 30; | |
EditorGUI.PropertyField(propRect, prop, true); | |
var childrenPropertiesCount = prop.CountInProperty(); | |
if (childrenPropertiesCount > 1) | |
r1.y += propertyFieldHeight * (childrenPropertiesCount - 1); | |
if (!EditorGUI.Toggle(checkRect, true)) | |
{ | |
var checkProperty = property.FindPropertyRelative(tuple.checkPropertyName); | |
checkProperty.boolValue = false; | |
} | |
r1.y += propertyFieldHeight; | |
} | |
// Calculate rects | |
// Set indent back to what it was | |
EditorGUI.indentLevel = indent; | |
EditorGUI.EndProperty(); | |
} | |
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) | |
{ | |
var totalElements = 2; | |
var iterator = property.Copy().GetEnumerator(); | |
var showNext = false; | |
while (iterator.MoveNext()) | |
{ | |
var prop = iterator.Current as SerializedProperty; | |
if (prop.name.ToLowerInvariant().StartsWith("check")) | |
{ | |
showNext = prop.boolValue; | |
continue; | |
} | |
if (!showNext) | |
{ | |
continue; | |
} | |
totalElements += prop.Copy().CountInProperty(); | |
showNext = false; | |
} | |
return totalElements * propertyFieldHeight; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment