VR4Medical/ICI/Library/PackageCache/com.unity.xr.interaction.toolkit@42ef3600567b/Editor/Inputs/Readers/InputFeatureUsageStringPropertyDrawer.cs
2025-07-29 13:45:50 +03:00

148 lines
6.0 KiB
C#

using System;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.XR;
using UnityEngine.XR.Interaction.Toolkit.Inputs.Readers;
namespace UnityEditor.XR.Interaction.Toolkit.Inputs.Readers
{
[CustomPropertyDrawer(typeof(InputFeatureUsageString<>), true)]
public class InputFeatureUsageStringPropertyDrawer : PropertyDrawer
{
class DropdownHandler
{
public SerializedProperty name { get; set; }
public void OnDropdownItemSelected(object userData)
{
if (name != null)
{
name.stringValue = (string)userData;
name.serializedObject.ApplyModifiedProperties();
}
}
}
bool m_ManualTextEditMode;
readonly GUIContent m_TempContent = new GUIContent();
GenericMenu m_UsagesMenu;
readonly DropdownHandler m_DropdownHandler = new DropdownHandler();
/// <inheritdoc />
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (property == null)
throw new ArgumentNullException(nameof(property));
return EditorGUIUtility.singleLineHeight;
}
/// <inheritdoc />
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (property == null)
throw new ArgumentNullException(nameof(property));
var name = property.FindPropertyRelative("m_Name");
// Using BeginProperty / EndProperty on the parent property means that
// prefab override logic works on the entire property.
label = EditorGUI.BeginProperty(position, label, property);
//EditorGUI.PropertyField(position, name, label);
var labelRect = position;
labelRect.width = EditorGUIUtility.labelWidth;
var lineRect = position;
lineRect.x += labelRect.width + 2f;
lineRect.width -= labelRect.width + 2f;
var nameTextRect = lineRect;
nameTextRect.width -= 20;
var editButtonRect = lineRect;
editButtonRect.x += nameTextRect.width;
editButtonRect.width = 20;
editButtonRect.height = 15;
EditorGUI.LabelField(labelRect, label);
// Get the generic type parameter of the InputFeatureUsageString<T> field, e.g. Vector2
// ReSharper disable PossibleNullReferenceException -- CustomPropertyDrawer already ensures that the base type exists
var propertyValueType = property.serializedObject.targetObject
.GetType().BaseType.GetField(property.name, BindingFlags.NonPublic | BindingFlags.Instance)
.FieldType.GetGenericArguments()[0];
var allSameType = true;
if (property.serializedObject.isEditingMultipleObjects)
{
allSameType = property.serializedObject.targetObjects.All(target =>
target.GetType().BaseType.GetField(property.name, BindingFlags.NonPublic | BindingFlags.Instance)
.FieldType.GetGenericArguments()[0] == propertyValueType);
}
// ReSharper restore PossibleNullReferenceException
if (m_ManualTextEditMode || !allSameType)
{
using (var check = new EditorGUI.ChangeCheckScope())
{
var newName = EditorGUI.TextField(nameTextRect, name.stringValue);
if (check.changed)
name.stringValue = newName;
}
}
else
{
m_TempContent.text = name.stringValue;
if (EditorGUI.DropdownButton(nameTextRect, m_TempContent, FocusType.Keyboard))
{
m_UsagesMenu = new GenericMenu();
var commonUsages = typeof(CommonUsages).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
foreach (var info in commonUsages)
{
// Exclude fields that have the Obsolete attribute
if (info.GetCustomAttributes(typeof(ObsoleteAttribute), false).Length > 0)
continue;
var inputFeatureUsage = info.GetValue(null);
var type = inputFeatureUsage.GetType();
if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(InputFeatureUsage<>))
continue;
var genericArgument = type.GetGenericArguments()[0];
if (genericArgument == propertyValueType)
{
// Get the InputFeatureUsage<>.name property
var namePropertyInfo = type.GetProperty("name");
if (namePropertyInfo == null)
continue;
var usageName = (string)namePropertyInfo.GetValue(inputFeatureUsage);
m_UsagesMenu.AddItem(new GUIContent(usageName), name.stringValue == usageName, m_DropdownHandler.OnDropdownItemSelected, usageName);
}
}
m_DropdownHandler.name = name;
m_UsagesMenu.ShowAsContext();
}
}
using (var check = new EditorGUI.ChangeCheckScope())
{
var newTextEditMode = GUI.Toggle(editButtonRect, m_ManualTextEditMode, Contents.editButton, EditorStyles.miniButton);
if (check.changed)
m_ManualTextEditMode = newTextEditMode;
}
EditorGUI.EndProperty();
}
static class Contents
{
public static readonly GUIContent editButton = EditorGUIUtility.TrTextContent("T", "Toggle between text editing and dropdown picker.");
}
}
}