VR Development Framework
v 1.0.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties Events Pages
AVRUI_Link.cs
1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4 using UnityEditor;
5 using System.Reflection;
6 using System.Linq;
7 
8 /// <summary>
9 /// Namespace of the arc-vr-ui Linking elements
10 /// </summary>
11 namespace AVR.UI.Link {
12  /// <summary>
13  /// Binds a given UI element (such as slider, toggle, dropdown or inputfield) with a given property or field of a given MonoBehaviour.
14  /// One intended use case would be an ingame options-screen to set, for instance, the FOV of a camera.
15  /// </summary>
16  [AVR.Core.Attributes.DocumentationUrl("class_a_v_r_1_1_u_i_1_1_link_1_1_a_v_r_u_i___link.html")]
17  public abstract class AVRUI_Link : AVR.Core.AVR_Behaviour
18  {
19  public enum MemberType { FIELD, PROPERTY }
20 
21  public abstract List<System.Type> validTypes { get; }
22 
23  public MonoBehaviour target;
24 
26  public string field;
27 
30 
31  void Start() {
32  init();
33  }
34 
35  void OnGUI() {
36  if(target && field!="") updateOutput();
37  }
38 
39  /// <summary>
40  /// Method is run on program start
41  /// </summary>
42  public abstract void init();
43 
44  /// <summary>
45  /// Method is run when the user selects a field in the inspector.
46  /// </summary>
47  public abstract void setup();
48 
49  /// <summary>
50  /// This method is executed when the runtime user changes the value of the UI element.
51  /// This method should change the field on the actual target respectively.
52  /// </summary>
53  public abstract void updateValue();
54 
55  /// <summary>
56  /// Method is run continously from OnGUI.
57  /// This method should update the value displayed by the UI when the target value changes.
58  /// </summary>
59  public abstract void updateOutput();
60  }
61 
62 
63 #if UNITY_EDITOR
64  [CustomEditor(typeof(AVRUI_Link), true)]
65  class AVRUI_Link_Editor : Editor
66  {
67  private bool show_fields = false;
68 
69  public override void OnInspectorGUI()
70  {
71  AVRUI_Link l = (AVRUI_Link)target;
72 
73  DrawDefaultInspector();
74 
75  EditorGUILayout.Space();
76 
77  // Allow to toggle fields
78  if (!show_fields)
79  {
80  if (GUILayout.Button("Show available fields", GUILayout.MaxWidth(200))) show_fields = true;
81  }
82  else if (GUILayout.Button("Hide available fields", GUILayout.MaxWidth(200)))
83  {
84  show_fields = false;
85  }
86 
87  // Show available fields
88  if (show_fields && l.target!=null)
89  {
90 
91  GUIStyle bttnStyle = new GUIStyle(GUI.skin.button);
92  bttnStyle.margin = new RectOffset(0, 0, 0, 0);
93 
94  BindingFlags commonFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.SetField | BindingFlags.SetProperty | BindingFlags.GetField | BindingFlags.GetProperty;
95 
96  using (new EditorGUILayout.HorizontalScope())
97  {
98  EditorGUILayout.BeginVertical();
99  EditorGUILayout.BeginFoldoutHeaderGroup(true, "Public Properties");
100  foreach (var v in l.target.GetType().GetProperties(System.Reflection.BindingFlags.Public | commonFlags))
101  {
102  //l.validTypes.Any((t) => v.PropertyType.IsSubclassOf(t))
103  if (l.validTypes.Contains(v.PropertyType) || l.validTypes.Any((t) => v.PropertyType.IsSubclassOf(t)) && v.CanRead && v.CanWrite)
104  if (GUILayout.Button(v.Name, bttnStyle, GUILayout.MaxWidth(200)))
105  {
106  l.memberType = AVRUI_Link.MemberType.PROPERTY;
107  l.field = v.Name;
108  l.setup();
109  }
110  }
111  EditorGUILayout.EndFoldoutHeaderGroup();
112  EditorGUILayout.EndVertical();
113 
114  EditorGUILayout.BeginVertical();
115  EditorGUILayout.BeginFoldoutHeaderGroup(true, "Private Properties");
116  foreach (var v in l.target.GetType().GetProperties(System.Reflection.BindingFlags.NonPublic | commonFlags))
117  {
118  if (l.validTypes.Contains(v.PropertyType) || l.validTypes.Any((t) => v.PropertyType.IsSubclassOf(t)) && v.CanRead && v.CanWrite)
119  if (GUILayout.Button(v.Name, bttnStyle, GUILayout.MaxWidth(200)))
120  {
121  l.memberType = AVRUI_Link.MemberType.PROPERTY;
122  l.field = v.Name;
123  l.setup();
124  }
125  }
126  EditorGUILayout.EndFoldoutHeaderGroup();
127  EditorGUILayout.EndVertical();
128  }
129 
130  using (new EditorGUILayout.HorizontalScope())
131  {
132  EditorGUILayout.BeginVertical();
133  EditorGUILayout.BeginFoldoutHeaderGroup(true, "Public Fields");
134  foreach (var v in l.target.GetType().GetFields(System.Reflection.BindingFlags.Public | commonFlags))
135  {
136  if (l.validTypes.Contains(v.FieldType) || l.validTypes.Any((t) => v.FieldType.IsSubclassOf(t)))
137  if (GUILayout.Button(v.Name, bttnStyle, GUILayout.MaxWidth(200)))
138  {
139  l.memberType = AVRUI_Link.MemberType.FIELD;
140  l.field = v.Name;
141  l.setup();
142  }
143  }
144  EditorGUILayout.EndFoldoutHeaderGroup();
145  EditorGUILayout.EndVertical();
146 
147  EditorGUILayout.BeginVertical();
148  EditorGUILayout.BeginFoldoutHeaderGroup(true, "Private Fields");
149  foreach (var v in l.target.GetType().GetFields(System.Reflection.BindingFlags.NonPublic | commonFlags))
150  {
151  if (l.validTypes.Contains(v.FieldType) || l.validTypes.Any((t) => v.FieldType.IsSubclassOf(t)))
152  if (GUILayout.Button(v.Name, bttnStyle, GUILayout.MaxWidth(200)))
153  {
154  l.memberType = AVRUI_Link.MemberType.FIELD;
155  l.field = v.Name;
156  l.setup();
157  }
158  }
159  EditorGUILayout.EndFoldoutHeaderGroup();
160  EditorGUILayout.EndVertical();
161  }
162  }
163  }
164 
165  private System.Boolean CanCovert(System.String value, System.Type type)
166  {
167  System.ComponentModel.TypeConverter converter = System.ComponentModel.TypeDescriptor.GetConverter(type);
168  return converter.IsValid(value);
169  }
170  }
171 #endif
172 }
Sets the documentation html file inside of Packages/com.avr.core/Documentation/html of a given class...
Makes a field read-only in the inspector