SteamVR_Input_Action_GenericPropertyEditor.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. using UnityEditor;
  2. using UnityEngine;
  3. using System.CodeDom;
  4. using Microsoft.CSharp;
  5. using System.IO;
  6. using System.CodeDom.Compiler;
  7. using System.Linq;
  8. using System.Collections.Generic;
  9. using System.Reflection;
  10. using System.Linq.Expressions;
  11. using System;
  12. namespace Valve.VR
  13. {
  14. public class SteamVR_Input_Action_GenericPropertyEditor<T> : PropertyDrawer where T : SteamVR_Action, new()
  15. {
  16. protected T[] actions;
  17. protected string[] enumItems;
  18. public int selectedIndex = notInitializedIndex;
  19. protected const int notInitializedIndex = -1;
  20. protected const int noneIndex = 0;
  21. protected int addIndex = 1;
  22. protected const string defaultPathTemplate = " \u26A0 Missing action: {0}";
  23. protected string defaultPathLabel = null;
  24. protected void Awake()
  25. {
  26. actions = SteamVR_Input.GetActions<T>();
  27. if (actions != null && actions.Length > 0)
  28. {
  29. List<string> enumList = actions.Select(action => action.fullPath).ToList();
  30. enumList.Insert(noneIndex, "None");
  31. //replace forward slashes with backslack instead
  32. for (int index = 0; index < enumList.Count; index++)
  33. enumList[index] = enumList[index].Replace('/', '\\');
  34. enumList.Add("Add...");
  35. enumItems = enumList.ToArray();
  36. }
  37. else
  38. {
  39. enumItems = new string[] { "None", "Add..." };
  40. }
  41. addIndex = enumItems.Length - 1;
  42. /*
  43. //keep sub menus:
  44. for (int index = 0; index < enumItems.Length; index++)
  45. if (enumItems[index][0] == '/')
  46. enumItems[index] = enumItems[index].Substring(1);
  47. */
  48. }
  49. public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
  50. {
  51. float height = base.GetPropertyHeight(property, label);
  52. SerializedProperty actionPathProperty = property.FindPropertyRelative("actionPath");
  53. if (string.IsNullOrEmpty(actionPathProperty.stringValue) == false)
  54. {
  55. if (selectedIndex == 0)
  56. return height * 2;
  57. }
  58. return height;
  59. }
  60. // Draw the property inside the given rect
  61. public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
  62. {
  63. if (SteamVR_Input.actions == null || SteamVR_Input.actions.Length == 0)
  64. {
  65. EditorGUI.BeginProperty(position, label, property);
  66. EditorGUI.LabelField(position, "Please generate SteamVR Input actions");
  67. EditorGUI.EndProperty();
  68. return;
  69. }
  70. if (enumItems == null || enumItems.Length == 0)
  71. {
  72. Awake();
  73. }
  74. // Using BeginProperty / EndProperty on the parent property means that
  75. // prefab override logic works on the entire property.
  76. EditorGUI.BeginProperty(position, label, property);
  77. SerializedProperty actionPathProperty = property.FindPropertyRelative("actionPath");
  78. string currentPath = null;
  79. if (actionPathProperty != null)
  80. {
  81. currentPath = actionPathProperty.stringValue;
  82. if (string.IsNullOrEmpty(currentPath) == false)
  83. {
  84. SteamVR_Action existingAction = SteamVR_Action.FindExistingActionForPartialPath(currentPath);
  85. if (existingAction != null)
  86. {
  87. if (currentPath != existingAction.GetPath())
  88. {
  89. actionPathProperty.stringValue = existingAction.GetPath();
  90. property.serializedObject.ApplyModifiedProperties();
  91. }
  92. currentPath = existingAction.GetPath();
  93. }
  94. for (int actionsIndex = 0; actionsIndex < actions.Length; actionsIndex++)
  95. {
  96. if (actions[actionsIndex].fullPath == currentPath)
  97. {
  98. selectedIndex = actionsIndex + 1; // account for none option
  99. break;
  100. }
  101. }
  102. }
  103. }
  104. if (selectedIndex == notInitializedIndex)
  105. selectedIndex = 0;
  106. Rect labelPosition = position;
  107. labelPosition.width = EditorGUIUtility.labelWidth;
  108. EditorGUI.LabelField(labelPosition, label);
  109. Rect fieldPosition = position;
  110. fieldPosition.x = (labelPosition.x + labelPosition.width);
  111. fieldPosition.width = EditorGUIUtility.currentViewWidth - (labelPosition.x + labelPosition.width) - 5;
  112. if (selectedIndex == 0 && string.IsNullOrEmpty(currentPath) == false)
  113. {
  114. if (defaultPathLabel == null)
  115. defaultPathLabel = string.Format(defaultPathTemplate, currentPath);
  116. Rect defaultLabelPosition = position;
  117. defaultLabelPosition.y = position.y + fieldPosition.height / 2f;
  118. EditorGUI.LabelField(defaultLabelPosition, defaultPathLabel);
  119. }
  120. bool showInputWindow = false;
  121. int wasSelected = selectedIndex;
  122. selectedIndex = EditorGUI.Popup(fieldPosition, selectedIndex, enumItems);
  123. if (selectedIndex != wasSelected)
  124. {
  125. if (selectedIndex == noneIndex || selectedIndex == notInitializedIndex)
  126. {
  127. selectedIndex = noneIndex;
  128. actionPathProperty.stringValue = null;
  129. }
  130. else if (selectedIndex == addIndex)
  131. {
  132. selectedIndex = wasSelected; // don't change the index
  133. showInputWindow = true;
  134. }
  135. else
  136. {
  137. int actionIndex = selectedIndex - 1; // account for none option
  138. actionPathProperty.stringValue = actions[actionIndex].GetPath();
  139. //property.objectReferenceValue = actions[actionIndex];
  140. }
  141. property.serializedObject.ApplyModifiedProperties();
  142. }
  143. EditorGUI.EndProperty();
  144. if (showInputWindow)
  145. SteamVR_Input_EditorWindow.ShowWindow(); //show the input window so they can add a new action
  146. }
  147. }
  148. }