/// <summary> /// Sweeps through the current scene for any MonoBehaviour objects, then checks each for any /// fields with the [DrawDebug] attribute, then finally stores this information in our Attributes list. /// </summary> private static void SweepForComponents() { if (attributes == null) { attributes = new List <MonoAttributeCollection>(); } if (activeSceneBuffer == null) { activeSceneBuffer = new List <MonoBehaviour>(); } activeSceneBuffer.Clear(); foreach (var type in preCheckedTypes) { activeSceneBuffer.AddRange(Object.FindObjectsOfType(type).AsEnumerable() as IEnumerable <MonoBehaviour>); } foreach (MonoBehaviour mono in activeSceneBuffer) { Type monoType = mono.GetType(); // See if this component has any fields with our attribute FieldInfo[] fields = monoType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); bool hasHandleAttribute = fields.Any(field => Attribute.GetCustomAttribute(field, typeof(SVHandleAttribute)) is SVHandleAttribute); if (!hasHandleAttribute) { continue; } // If we haven't exited by this point, we know there is atleast one field with our attribute. MonoAttributeCollection attrib = GetOrCreateAttributeCollection(mono); foreach (FieldInfo field in fields) { SVHandleAttribute svHandleAttributeAttrib = Attribute.GetCustomAttribute(field, typeof(SVHandleAttribute)) as SVHandleAttribute; if (svHandleAttributeAttrib == null) { continue; } if (attrib.SVHandles.ContainsKey(field)) { continue; } attrib.SVHandles.Add(field, svHandleAttributeAttrib); } } }
/// <summary> /// Searches through out attribute list to see if one exists with the given mono instance. /// If none exist, it creates a new AttributeInstance with the given mono instance and adds it to Attributes. /// </summary> /// <param name="mono"></param> /// <returns></returns> private static MonoAttributeCollection GetOrCreateAttributeCollection(MonoBehaviour mono) { foreach (var attribute in attributes) { if (attribute.MonoInstance == mono) { return(attribute); } } var attributeCollection = new MonoAttributeCollection(mono); attributes.Add(attributeCollection); return(attributeCollection); }
private static void OnSceneGUI(SceneView sceneView) { if (attributes == null) { SweepForComponents(); } Color cachedHandlesColor = Handles.color; for (int i = attributes.Count; i >= 0; i--) { MonoAttributeCollection attribute = attributes[i]; // If there is no mono instance, assume our component has been removed. if (attribute.MonoInstance == null) { attributes.Remove(attribute); continue; } if (displayMode == DisplayMode.SelectedObject && !Selection.Contains(attribute.MonoInstance.gameObject)) { continue; } // Draw our SVDebugs foreach (var kvPair in attribute.SVHandles) { object value = kvPair.Key.GetValue(attribute.MonoInstance); Type type = kvPair.Key.FieldType; if (value == null) { attributes.Remove(attribute); break; } if (!handleDisplays.ContainsKey(type)) { Debug.LogWarning("Attempt to draw debug for a type which doesn't have a ITypeDisplay.\nPerhaps you should add one?"); continue; } SVArgs args = new SVArgs(value, attribute.MonoInstance); Handles.color = attribute.SVHandles[kvPair.Key].Color; EditorGUI.BeginChangeCheck(); { // If the attribute has a specific Display defined, use that. if (kvPair.Value.Type != null) { handleDisplays[type][kvPair.Value.Type].Draw(args, ref value); } else { SVHandleDisplay currentDisp = null; using (var e = handleDisplays[type].Values.GetEnumerator()) { while (e.MoveNext()) { if (currentDisp == null || e.Current.Priority > currentDisp.Priority) { currentDisp = e.Current; } e.MoveNext(); } } if (currentDisp != null) { currentDisp.Draw(args, ref value); } } } if (EditorGUI.EndChangeCheck()) { kvPair.Key.SetValue(attribute.MonoInstance, value); } } } Handles.color = cachedHandlesColor; }