Scripts/Editor/CallbackHandlers/ValuePathMatcherPropertyDrawer.cs (201 lines of code) (raw):
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the license found in the
* LICENSE file in the root directory of this source tree.
*/
using System.Collections.Generic;
using Facebook.WitAi.Data;
using UnityEditor;
using UnityEngine;
namespace Facebook.WitAi.CallbackHandlers
{
public class ValuePathMatcherPropertyDrawer : PropertyDrawer
{
private string currentEditPath;
class Properties
{
public const string witValueRef = "witValueReference";
public const string path = "path";
public const string contentRequired = "contentRequired";
public const string matchMethod = "matchMethod";
public const string comparisonMethod = "comparisonMethod";
public const string matchValue = "matchValue";
public const string floatingPointComparisonTolerance =
"floatingPointComparisonTolerance";
}
private Dictionary<string, bool> foldouts =
new Dictionary<string, bool>();
private string GetPropertyPath(SerializedProperty property)
{
var valueRefProp = property.FindPropertyRelative(Properties.witValueRef);
if (valueRefProp.objectReferenceValue)
{
return ((WitValue) valueRefProp.objectReferenceValue).path;
}
return property.FindPropertyRelative(Properties.path).stringValue;
}
private bool IsEditingProperty(SerializedProperty property)
{
var path = GetPropertyPath(property);
return path == currentEditPath || string.IsNullOrEmpty(path);
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
float height = 0;
// Path
height += EditorGUIUtility.singleLineHeight;
if (IsExpanded(property))
{
// Content Required
height += EditorGUIUtility.singleLineHeight;
// Match Method
height += EditorGUIUtility.singleLineHeight;
if (ComparisonMethodsVisible(property))
{
// Comparison Method
height += EditorGUIUtility.singleLineHeight;
}
if (ComparisonValueVisible(property))
{
// Comparison Value
height += EditorGUIUtility.singleLineHeight;
}
if (FloatingToleranceVisible(property))
{
// Floating Point Tolerance
height += EditorGUIUtility.singleLineHeight;
}
height += 4;
}
return height;
}
private bool IsExpanded(SerializedProperty property)
{
return foldouts.TryGetValue(GetPropertyPath(property), out bool value) && value;
}
private bool Foldout(Rect rect, SerializedProperty property)
{
var path = GetPropertyPath(property);
if (!foldouts.TryGetValue(path, out var value))
{
foldouts[path] = false;
}
foldouts[path] = EditorGUI.Foldout(rect, value, "");
return foldouts[path];
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var rect = new Rect(position)
{
height = EditorGUIUtility.singleLineHeight
};
var path = property.FindPropertyRelative(Properties.path);
var valueRefProp = property.FindPropertyRelative(Properties.witValueRef);
var editIconWidth = 24;
var pathRect = new Rect(rect);
pathRect.width -= editIconWidth;
var pathValue = GetPropertyPath(property);
if (IsEditingProperty(property))
{
if (!valueRefProp.objectReferenceValue)
{
pathRect.width -= WitStyles.IconButtonSize;
var value = EditorGUI.TextField(pathRect, path.stringValue);
if (value != path.stringValue)
{
path.stringValue = value;
}
pathRect.width += WitStyles.IconButtonSize;
var pickerRect = new Rect(pathRect)
{
x = pathRect.x + pathRect.width - 20,
width = 20
};
if (GUI.Button(pickerRect, WitStyles.ObjectPickerIcon, "Label"))
{
var id = EditorGUIUtility.GetControlID(FocusType.Passive) + 100;
EditorGUIUtility.ShowObjectPicker<WitValue>(
(WitValue) valueRefProp.objectReferenceValue, false, "", id);
}
}
else
{
EditorGUI.PropertyField(pathRect, valueRefProp, new GUIContent());
}
if (Event.current.commandName == "ObjectSelectorClosed")
{
valueRefProp.objectReferenceValue = EditorGUIUtility.GetObjectPickerObject();
}
pathValue = GetPropertyPath(property);
if (pathValue != currentEditPath && null != currentEditPath)
{
foldouts[currentEditPath] = false;
currentEditPath = GetPropertyPath(property);
foldouts[currentEditPath] = true;
}
}
else
{
if (valueRefProp.objectReferenceValue)
{
EditorGUI.LabelField(pathRect, valueRefProp.objectReferenceValue.name);
}
else
{
EditorGUI.LabelField(pathRect, path.stringValue);
}
}
var editRect = new Rect(rect)
{
x = pathRect.x + pathRect.width + 8
};
if (Foldout(rect, property))
{
if (GUI.Button(editRect, WitStyles.EditIcon, "Label"))
{
if (currentEditPath == pathValue)
{
currentEditPath = null;
}
else
{
currentEditPath = pathValue;
}
}
rect.x += WitStyles.IconButtonSize;
rect.width -= WitStyles.IconButtonSize;
rect.y += rect.height;
EditorGUI.PropertyField(rect, property.FindPropertyRelative(Properties.contentRequired));
rect.y += rect.height;
EditorGUI.PropertyField(rect, property.FindPropertyRelative(Properties.matchMethod));
if (ComparisonMethodsVisible(property))
{
rect.y += rect.height;
EditorGUI.PropertyField(rect,
property.FindPropertyRelative(Properties.comparisonMethod));
}
if (ComparisonValueVisible(property))
{
rect.y += rect.height;
EditorGUI.PropertyField(rect,
property.FindPropertyRelative(Properties.matchValue));
}
if (FloatingToleranceVisible(property))
{
rect.y += rect.height;
EditorGUI.PropertyField(rect,
property.FindPropertyRelative(Properties.floatingPointComparisonTolerance));
}
}
}
private bool ComparisonMethodsVisible(SerializedProperty property)
{
var matchedMethodProperty = property.FindPropertyRelative(Properties.matchMethod);
return matchedMethodProperty.enumValueIndex > (int) MatchMethod.RegularExpression;
}
private bool ComparisonValueVisible(SerializedProperty property)
{
var matchedMethodProperty = property.FindPropertyRelative(Properties.matchMethod);
return matchedMethodProperty.enumValueIndex > 0;
}
private bool FloatingToleranceVisible(SerializedProperty property)
{
var matchedMethodProperty = property.FindPropertyRelative(Properties.matchMethod);
var comparisonMethodProperty =
property.FindPropertyRelative(Properties.comparisonMethod);
var comparisonMethod = comparisonMethodProperty.enumValueIndex;
return matchedMethodProperty.enumValueIndex >= (int) MatchMethod.FloatComparison &&
(comparisonMethod == (int) ComparisonMethod.Equals || comparisonMethod == (int) ComparisonMethod.NotEquals);
}
}
}