public static void OnSceneTreeReflectProperty(SceneExplorerState state, ReferenceChain refChain, System.Object obj, PropertyInfo property) { if (!SceneExplorerCommon.SceneTreeCheckDepth(refChain)) { return; } if (obj == null || property == null) { SceneExplorerCommon.OnSceneTreeMessage(refChain, "null"); return; } var hash = refChain.GetHashCode().ToString(); GUILayout.BeginHorizontal(); GUILayout.Space(ModTools.Instance.config.sceneExplorerTreeIdentSpacing * refChain.Ident); bool propertyWasEvaluated = false; object value = null; Exception exceptionOnGetting = null; if (property.CanRead && ModTools.Instance.config.sceneExplorerEvaluatePropertiesAutomatically || state.evaluatedProperties.ContainsKey(refChain)) { try { value = property.GetValue(obj, null); propertyWasEvaluated = true; } catch (Exception e) { exceptionOnGetting = e; } if (value != null && exceptionOnGetting == null) { GUIExpander.ExpanderControls(state, refChain, property.PropertyType, obj); } } GUI.contentColor = Color.white; if (!property.CanWrite) { GUI.enabled = false; } if (ModTools.Instance.config.sceneExplorerShowModifiers) { GUI.contentColor = ModTools.Instance.config.memberTypeColor; GUILayout.Label("property "); if (!property.CanWrite) { GUI.contentColor = ModTools.Instance.config.keywordColor; GUILayout.Label("const "); } } GUI.contentColor = ModTools.Instance.config.typeColor; GUILayout.Label(property.PropertyType.ToString() + " "); GUI.contentColor = ModTools.Instance.config.nameColor; GUILayout.Label(property.Name); GUI.contentColor = Color.white; GUILayout.Label(" = "); GUI.contentColor = ModTools.Instance.config.valueColor; if (!ModTools.Instance.config.sceneExplorerEvaluatePropertiesAutomatically && !state.evaluatedProperties.ContainsKey(refChain)) { GUI.enabled = true; if (GUILayout.Button("Evaluate")) { state.evaluatedProperties.Add(refChain, true); } } else { if (!propertyWasEvaluated && property.CanRead) { try { value = property.GetValue(obj, null); propertyWasEvaluated = true; } catch (Exception e) { exceptionOnGetting = e; } } if (exceptionOnGetting != null) { GUI.contentColor = Color.red; GUILayout.Label("Exception happened when getting property value"); GUI.contentColor = Color.white; GUI.enabled = true; GUIStackTrace.StackTraceButton(new StackTrace(exceptionOnGetting, true)); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); return; } if (value == null || !TypeUtil.IsSpecialType(property.PropertyType)) { if (property.CanRead) { GUILayout.Label(value == null ? "null" : value.ToString()); } else { GUILayout.Label("(no get method)"); } GUI.contentColor = Color.white; } else { try { var newValue = GUIControls.EditorValueField(refChain, hash, property.PropertyType, value); if (newValue != value) { property.SetValue(obj, newValue, null); } } catch (Exception) { if (property.CanRead) { GUILayout.Label(value == null ? "null" : value.ToString()); } else { GUILayout.Label("(no get method)"); } GUI.contentColor = Color.white; } } } GUI.enabled = true; GUI.contentColor = Color.white; GUILayout.FlexibleSpace(); if (GUILayout.Button("Watch")) { ModTools.Instance.watches.AddWatch(refChain); } GUIButtons.SetupButtons(property.PropertyType, value, refChain); object paste = null; var doPaste = property.CanWrite; if (doPaste) { doPaste = GUIButtons.SetupPasteButon(property.PropertyType, out paste); } GUILayout.EndHorizontal(); if (value != null && state.expandedObjects.ContainsKey(refChain)) { if (value is GameObject) { var go = value as GameObject; foreach (var component in go.GetComponents <Component>()) { GUIComponent.OnSceneTreeComponent(state, refChain, component); } } else if (value is Transform) { GUITransform.OnSceneTreeReflectUnityEngineTransform(refChain, (Transform)value); } else { GUIReflect.OnSceneTreeReflect(state, refChain, value); } } if (doPaste) { try { property.SetValue(obj, paste, null); } catch (Exception e) { Log.Warning(e.Message); } } }
public static void OnSceneTreeReflect(SceneExplorerState state, ReferenceChain refChain, System.Object obj, bool rawReflection = false) { if (!SceneExplorerCommon.SceneTreeCheckDepth(refChain)) { return; } if (obj == null) { SceneExplorerCommon.OnSceneTreeMessage(refChain, "null"); return; } Type type = obj.GetType(); if (!rawReflection) { if (state.preventCircularReferences.ContainsKey(obj.GetHashCode())) { SceneExplorerCommon.OnSceneTreeMessage(refChain, "Circular reference detected"); return; } state.preventCircularReferences.Add(obj.GetHashCode(), true); if (type == typeof(UnityEngine.Transform)) { GUITransform.OnSceneTreeReflectUnityEngineTransform(refChain, (UnityEngine.Transform)obj); return; } if (TypeUtil.IsList(obj)) { GUIList.OnSceneTreeReflectIList(state, refChain, obj); return; } if (TypeUtil.IsCollection(obj)) { GUICollection.OnSceneTreeReflectICollection(state, refChain, obj); return; } if (TypeUtil.IsEnumerable(obj)) { GUIEnumerable.OnSceneTreeReflectIEnumerable(state, refChain, obj); return; } if (type == typeof(Material)) { GUIMaterial.OnSceneReflectUnityEngineMaterial(state, refChain, (UnityEngine.Material)obj); return; } if (type == typeof(Mesh)) { if (!((Mesh)obj).isReadable) { SceneExplorerCommon.OnSceneTreeMessage(refChain, "Mesh is not readable"); return; } } } var members = TypeUtil.GetAllMembers(type, ModTools.Instance.config.sceneExplorerShowInheritedMembers); if (ModTools.Instance.config.sceneExplorerSortAlphabetically) { Array.Sort(members, (info, info1) => string.Compare(info.Name, info1.Name, StringComparison.Ordinal)); } foreach (MemberInfo member in members) { if (member.MemberType == MemberTypes.Field && ModTools.Instance.config.sceneExplorerShowFields) { var field = (FieldInfo)member; try { GUIField.OnSceneTreeReflectField(state, refChain.Add(field), obj, field); } catch (Exception ex) { SceneExplorerCommon.OnSceneTreeMessage(refChain, $"Exception when fetching field \"{field.Name}\" - {ex.Message}\n{ex.StackTrace}"); } } else if (member.MemberType == MemberTypes.Property && ModTools.Instance.config.sceneExplorerShowProperties) { var property = (PropertyInfo)member; try { GUIProperty.OnSceneTreeReflectProperty(state, refChain.Add(property), obj, property); } catch (Exception ex) { SceneExplorerCommon.OnSceneTreeMessage(refChain, $"Exception when fetching property \"{property.Name}\" - {ex.Message}\n{ex.StackTrace}"); } } else if (member.MemberType == MemberTypes.Method && ModTools.Instance.config.sceneExplorerShowMethods) { var method = (MethodInfo)member; try { GUIMethod.OnSceneTreeReflectMethod(refChain.Add(method), obj, method); } catch (Exception ex) { SceneExplorerCommon.OnSceneTreeMessage(refChain, $"Exception when fetching method \"{method.Name}\" - {ex.Message}"); } } } }
public static void OnSceneTreeReflectICollection(SceneExplorerState state, ReferenceChain refChain, System.Object myProperty) { if (!SceneExplorerCommon.SceneTreeCheckDepth(refChain)) { return; } var collection = myProperty as ICollection; if (collection == null) { return; } var oldRefChain = refChain; var collectionSize = collection.Count; if (collectionSize == 0) { GUILayout.BeginHorizontal(); GUI.contentColor = Color.yellow; GUILayout.Label("Collection is empty!"); GUI.contentColor = Color.white; GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); return; } int arrayStart; int arrayEnd; GUICollectionNavigation.SetUpCollectionNavigation("Collection", state, refChain, oldRefChain, collectionSize, out arrayStart, out arrayEnd); int count = 0; foreach (var value in collection) { if (count < arrayStart) { count++; continue; } refChain = oldRefChain.Add(count); var type = value.GetType(); GUILayout.BeginHorizontal(); GUILayout.Space(ModTools.Instance.config.sceneExplorerTreeIdentSpacing * refChain.Ident); GUIExpander.ExpanderControls(state, refChain, type); GUI.contentColor = ModTools.Instance.config.typeColor; GUILayout.Label(type.ToString() + " "); GUI.contentColor = ModTools.Instance.config.nameColor; GUILayout.Label($"{oldRefChain.LastItemName}.[{count}]"); GUI.contentColor = Color.white; GUILayout.Label(" = "); GUI.contentColor = ModTools.Instance.config.valueColor; GUILayout.Label(value == null ? "null" : value.ToString()); GUI.contentColor = Color.white; GUILayout.FlexibleSpace(); GUIButtons.SetupButtons(type, value, refChain); GUILayout.EndHorizontal(); if (!TypeUtil.IsSpecialType(type) && state.expandedObjects.ContainsKey(refChain)) { if (value is GameObject) { var go = value as GameObject; foreach (var component in go.GetComponents <Component>()) { GUIComponent.OnSceneTreeComponent(state, refChain, component); } } else if (value is Transform) { GUITransform.OnSceneTreeReflectUnityEngineTransform(refChain, (Transform)value); } else { GUIReflect.OnSceneTreeReflect(state, refChain, value); } } count++; if (count > arrayEnd) { break; } } }
public static void OnSceneTreeReflectField(SceneExplorerState state, ReferenceChain refChain, object obj, FieldInfo field) { var hash = refChain.GetHashCode().ToString(); if (!SceneExplorerCommon.SceneTreeCheckDepth(refChain)) { return; } if (obj == null || field == null) { SceneExplorerCommon.OnSceneTreeMessage(refChain, "null"); return; } GUILayout.BeginHorizontal(); GUILayout.Space(ModTools.Instance.config.sceneExplorerTreeIdentSpacing * refChain.Ident); GUI.contentColor = Color.white; object value = null; try { value = field.GetValue(obj); } catch (Exception e) { UnityEngine.Debug.LogException(e); } if (value != null) { GUIExpander.ExpanderControls(state, refChain, field.FieldType); } if (field.IsInitOnly) { GUI.enabled = false; } if (ModTools.Instance.config.sceneExplorerShowModifiers) { GUI.contentColor = ModTools.Instance.config.modifierColor; if (field.IsPublic) { GUILayout.Label("public "); } else if (field.IsPrivate) { GUILayout.Label("private "); } GUI.contentColor = ModTools.Instance.config.memberTypeColor; GUILayout.Label("field "); if (field.IsStatic) { GUI.contentColor = ModTools.Instance.config.keywordColor; GUILayout.Label("static "); } if (field.IsInitOnly) { GUI.contentColor = ModTools.Instance.config.keywordColor; GUILayout.Label("const "); } } GUI.contentColor = ModTools.Instance.config.typeColor; GUILayout.Label(field.FieldType + " "); GUI.contentColor = ModTools.Instance.config.nameColor; GUILayout.Label(field.Name); GUI.contentColor = Color.white; GUI.contentColor = Color.white; GUILayout.Label(" = "); GUI.contentColor = ModTools.Instance.config.valueColor; if (value == null || !TypeUtil.IsSpecialType(field.FieldType)) { GUILayout.Label(value?.ToString() ?? "null"); } else { try { var newValue = GUIControls.EditorValueField(refChain, hash, field.FieldType, value); if (newValue != value) { field.SetValue(obj, newValue); } } catch (Exception) { GUILayout.Label(value.ToString()); } } GUI.enabled = true; GUI.contentColor = Color.white; GUILayout.FlexibleSpace(); if (GUILayout.Button("Watch")) { ModTools.Instance.watches.AddWatch(refChain); } GUIButtons.SetupButtons(field.FieldType, value, refChain); object paste = null; var doPaste = !field.IsLiteral && !field.IsInitOnly; if (doPaste) { doPaste = GUIButtons.SetupPasteButon(field.FieldType, out paste); } GUILayout.EndHorizontal(); if (value != null && !TypeUtil.IsSpecialType(field.FieldType) && state.expandedObjects.ContainsKey(refChain)) { if (value is GameObject) { var go = value as GameObject; foreach (var component in go.GetComponents <Component>()) { GUIComponent.OnSceneTreeComponent(state, refChain, component); } } else if (value is Transform) { GUITransform.OnSceneTreeReflectUnityEngineTransform(refChain, (Transform)value); } else { GUIReflect.OnSceneTreeReflect(state, refChain, value); } } if (doPaste) { try { field.SetValue(obj, paste); } catch (Exception e) { Log.Warning(e.Message); } } }
public static void OnSceneTreeReflect(SceneExplorerState state, ReferenceChain refChain, object obj, bool rawReflection, TypeUtil.SmartType smartType = TypeUtil.SmartType.Undefined, string filter = "") { if (!SceneExplorerCommon.SceneTreeCheckDepth(refChain)) { return; } if (obj == null) { SceneExplorerCommon.OnSceneTreeMessage(refChain, "null"); return; } var type = obj.GetType(); if (!rawReflection) { if (!type.IsValueType && state.PreventCircularReferences.Contains(obj)) { try { GUI.contentColor = Color.yellow; SceneExplorerCommon.OnSceneTreeMessage(refChain, "Circular reference detected"); } finally { GUI.contentColor = Color.white; } return; } state.PreventCircularReferences.Add(obj); if (type == typeof(Transform)) { GUITransform.OnSceneTreeReflectUnityEngineTransform(refChain, (Transform)obj); return; } if (TypeUtil.IsList(obj)) { GUIList.OnSceneTreeReflectIList(state, refChain, obj, smartType); return; } if (TypeUtil.IsCollection(obj)) { GUICollection.OnSceneTreeReflectICollection(state, refChain, obj, smartType); return; } if (TypeUtil.IsEnumerable(obj)) { GUIEnumerable.OnSceneTreeReflectIEnumerable(state, refChain, obj, smartType); return; } if (type == typeof(Material)) { GUIMaterial.OnSceneReflectUnityEngineMaterial(state, refChain, (Material)obj); return; } if (type == typeof(Mesh) && !((Mesh)obj).isReadable) { SceneExplorerCommon.OnSceneTreeMessage(refChain, "Mesh is not readable"); return; } } var members = TypeUtil.GetAllMembers(type, MainWindow.Instance.Config.ShowInheritedMembers); if (MainWindow.Instance.Config.SortItemsAlphabetically) { Array.Sort(members, (x, y) => string.CompareOrdinal(x.ReflectionInfo.Name, y.ReflectionInfo.Name)); } var matchingMembers = 0; foreach (var member in members) { var filterMatchFrom = -1; if (!filter.IsNullOrEmpty() && (filterMatchFrom = member.ReflectionInfo.Name.IndexOf(filter, StringComparison.OrdinalIgnoreCase)) < 0) { continue; } matchingMembers++; switch (member.ReflectionInfo.MemberType) { case MemberTypes.Field when MainWindow.Instance.Config.ShowFields: { var field = (FieldInfo)member.ReflectionInfo; if (field.IsLiteral && !field.IsInitOnly && !MainWindow.Instance.Config.ShowConsts) { continue; } try { GUIField.OnSceneTreeReflectField(state, refChain.Add(field), obj, field, TypeUtil.OverrideSmartType(member.DetectedType, field.Name, obj), filterMatchFrom, filter.Length); } catch (Exception ex) { SceneExplorerCommon.OnSceneTreeMessage(refChain, $"Exception when fetching field \"{field.Name}\" - {ex.Message}\n{ex.StackTrace}"); } break; } case MemberTypes.Property when MainWindow.Instance.Config.ShowProperties: { var property = (PropertyInfo)member.ReflectionInfo; if (property.GetIndexParameters().Length > 0) { continue; // TODO: add support for indexers } try { GUIProperty.OnSceneTreeReflectProperty(state, refChain.Add(property), obj, property, TypeUtil.OverrideSmartType(member.DetectedType, property.Name, obj), filterMatchFrom, filter.Length); } catch (Exception ex) { SceneExplorerCommon.OnSceneTreeMessage(refChain, $"Exception when fetching property \"{property.Name}\" - {ex.Message}\n{ex.StackTrace}"); } break; } case MemberTypes.Method when MainWindow.Instance.Config.ShowMethods: { var method = (MethodInfo)member.ReflectionInfo; try { GUIMethod.OnSceneTreeReflectMethod(refChain.Add(method), obj, method, filterMatchFrom, filter.Length); } catch (Exception ex) { SceneExplorerCommon.OnSceneTreeMessage(refChain, $"Exception when fetching method \"{method.Name}\" - {ex.Message}"); } break; } } } if (filter.IsNullOrEmpty() || members.Length <= 0 || matchingMembers != 0) { return; } GUI.contentColor = Color.yellow; SceneExplorerCommon.OnSceneTreeMessage(refChain, "No members matching the search term found!"); GUI.contentColor = Color.white; }
public static void OnSceneTreeReflectIEnumerable(SceneExplorerState state, ReferenceChain refChain, object myProperty) { if (!SceneExplorerCommon.SceneTreeCheckDepth(refChain)) { return; } var enumerable = myProperty as IEnumerable; if (enumerable == null) { return; } int count = 0; var oldRefChain = refChain; foreach (var value in enumerable) { refChain = oldRefChain.Add(count); var type = value.GetType(); GUILayout.BeginHorizontal(); GUILayout.Space(ModTools.Instance.config.sceneExplorerTreeIdentSpacing * refChain.Ident); GUIExpander.ExpanderControls(state, refChain, type); GUI.contentColor = ModTools.Instance.config.typeColor; GUILayout.Label(type.ToString() + " "); GUI.contentColor = ModTools.Instance.config.nameColor; GUILayout.Label($"{oldRefChain.LastItemName}.[{count}]"); GUI.contentColor = Color.white; GUILayout.Label(" = "); GUI.contentColor = ModTools.Instance.config.valueColor; GUILayout.Label(value == null ? "null" : value.ToString()); GUI.contentColor = Color.white; GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); if (!TypeUtil.IsSpecialType(type) && state.expandedObjects.ContainsKey(refChain)) { if (value is GameObject) { var go = value as GameObject; foreach (var component in go.GetComponents <Component>()) { GUIComponent.OnSceneTreeComponent(state, refChain, component); } } else if (value is Transform) { GUITransform.OnSceneTreeReflectUnityEngineTransform(refChain, (Transform)value); } else { GUIReflect.OnSceneTreeReflect(state, refChain, value); } } count++; if (count >= 1024) { SceneExplorerCommon.OnSceneTreeMessage(refChain, "Array too large to display"); break; } } }
public static void OnSceneTreeReflectIList(SceneExplorerState state, ReferenceChain refChain, System.Object myProperty) { if (!SceneExplorerCommon.SceneTreeCheckDepth(refChain)) { return; } var list = myProperty as IList; if (list == null) { return; } var oldRefChain = refChain; var collectionSize = list.Count; if (collectionSize == 0) { GUILayout.BeginHorizontal(); GUI.contentColor = Color.yellow; GUILayout.Label("List is empty!"); GUI.contentColor = Color.white; GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); return; } int arrayStart; int arrayEnd; GUICollectionNavigation.SetUpCollectionNavigation("List", state, refChain, oldRefChain, collectionSize, out arrayStart, out arrayEnd); for (int i = arrayStart; i <= arrayEnd; i++) { refChain = oldRefChain.Add(i); if (list[i] == null) { continue; } GUILayout.BeginHorizontal(); GUILayout.Space(ModTools.Instance.config.sceneExplorerTreeIdentSpacing * refChain.Ident); GUI.contentColor = Color.white; var type = list[i] == null ? null : list[i].GetType(); GUIExpander.ExpanderControls(state, refChain, type); GUI.contentColor = ModTools.Instance.config.typeColor; GUILayout.Label($"{type} "); GUI.contentColor = ModTools.Instance.config.nameColor; GUILayout.Label($"{oldRefChain.LastItemName}.[{i}]"); GUI.contentColor = Color.white; GUILayout.Label(" = "); GUI.contentColor = ModTools.Instance.config.valueColor; if (list[i] == null || !TypeUtil.IsSpecialType(list[i].GetType())) { GUILayout.Label(list[i] == null ? "null" : list[i].ToString()); } else { try { var newValue = GUIControls.EditorValueField(refChain, refChain.ToString(), list[i].GetType(), list[i]); if (newValue != list[i]) { list[i] = newValue; } } catch (Exception) { GUILayout.Label(list[i] == null ? "null" : list[i].ToString()); } } GUI.contentColor = Color.white; GUILayout.FlexibleSpace(); GUIButtons.SetupButtons(type, list[i], refChain); GUILayout.EndHorizontal(); if (!TypeUtil.IsSpecialType(type) && state.expandedObjects.ContainsKey(refChain)) { if (list[i] is GameObject) { var go = list[i] as GameObject; foreach (var component in go.GetComponents <Component>()) { GUIComponent.OnSceneTreeComponent(state, refChain, component); } } else if (list[i] is Transform) { GUITransform.OnSceneTreeReflectUnityEngineTransform(refChain, (Transform)list[i]); } else { GUIReflect.OnSceneTreeReflect(state, refChain, list[i]); } } } }