private IEnumerable <IValueEntity> GetChildrenImpl(IPresentationOptions options, CancellationToken token) { myGetElementMethod = MetadataTypeLiteEx.LookupInstanceMethodSafe(mySerializedPropertyRole.ReifiedType.MetadataType, myGetMethodElementSelector, false); if (myGetElementMethod == null) { myLogger.Warn("Cannot find GetArrayElementAtIndex/GetFixedBufferElementAtIndex method"); yield break; } if (options.ClusterArrays) { foreach (var valueEntity in GetChunkedChildren(mySerializedPropertyRole, 0, myArraySize, options, token)) { yield return(valueEntity); } } else { for (var i = 0; i < myArraySize; i++) { token.ThrowIfCancellationRequested(); yield return(GetElementValueAt(mySerializedPropertyRole, i, options)); } } }
public override bool IsApplicable(IValueRole <TValue> role, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder) { return(myUnityOptions.ExtensionsEnabled && role.ValueReference is ExtraDetailValueReferenceDecorator <TValue>); }
public override bool IsApplicable(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder) { return(myUnityOptions.ExtensionsEnabled && instanceType.Is("UnityEditor.SerializedProperty")); }
private IEnumerable <IValueEntity> EnumerateMembersWithBaseNode(IObjectValueRole <TValue> valueRole, IPresentationOptions options, CancellationToken token, IValueServicesFacade <TValue> valueServices) { var baseRole = FindNextBaseRoleWithVisibleMembers(valueRole); if (baseRole != null) { yield return(new ConcreteObjectRoleReference <TValue>(baseRole, "base", false, ValueOriginKind.Base, ValueFlags.None).ToValue(valueServices)); } var propertiesAndFields = GetPropertiesAndFields(valueRole) .Where(IsAllowedReference) .OrderBy(IdentityFunc <IValueReference <TValue> > .Instance, ByNameReferenceComparer <TValue> .Instance); foreach (var member in ChildrenRenderingUtil.RenderReferencesWithVisibilityGroups(propertiesAndFields, options, token, valueServices)) { yield return(member); } foreach (var staticMember in ChildrenRenderingUtil.EnumerateStaticMembersIfNeeded(valueRole, options, token, valueServices)) { yield return(staticMember); } }
protected override IEnumerable <IValueEntity> GetChildren(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder, CancellationToken token) { // GetChildren is always called with evaluation enabled (e.g. to calculate IEnumerable's "Results" node). // If the user has disabled "Allow property evaluation..." we shouldn't show the "Scene Path" item. // Ideally, we should add it with a "Refresh" link to calculate it if required. This involves returning a // reference to calculate the value rather than calculating it eagerly. // TODO: Make "Scene Path" lazy in 212 if (mySession.EvaluationOptions.AllowTargetInvoke) { var scenePathValue = ScenePathValueHelper.GetScenePathValue(valueRole, options, ValueServices, Logger); if (scenePathValue != null) { yield return(scenePathValue); } } yield return(new GameObjectComponentsGroup(valueRole, ValueServices, Logger)); yield return(new GameObjectChildrenGroup(valueRole, ValueServices, Logger)); foreach (var valueEntity in base.GetChildren(valueRole, instanceType, options, dataHolder, token)) { yield return(valueEntity); } }
protected IEnumerable <IValueEntity> RenderChildren(IObjectValueRole <TValue> valueRole, IEnumerable <IValueReference <TValue> > references, IPresentationOptions options, CancellationToken token) { if (!options.FlattenHierarchy) { // Add when rendering to avoid sorting issues var baseRole = FindNextBaseRoleWithVisibleMembers(valueRole); if (baseRole != null) { yield return(new ConcreteObjectRoleReference <TValue>(baseRole, "base", false, ValueOriginKind.Base, ValueFlags.None).ToValue(ValueServices)); } } foreach (var memberValue in ChildrenRenderingUtil.RenderReferencesWithVisibilityGroups(references, options, token, ValueServices)) { yield return(memberValue); } foreach (var staticMember in ChildrenRenderingUtil.EnumerateStaticMembersIfNeeded(valueRole, options, token, ValueServices)) { yield return(staticMember); } }
protected override IEnumerable <IValueEntity> GetChildren(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder, CancellationToken token) { // GetChildren is passed options that always allow evaluation, e.g. to calculate IEnumerable's "Results" // node. We eagerly evaluate Scene Path here, we should return a lazy reference to allow evaluating during // presentation, so that we get the "Refresh" link if the user has disabled evaluation // TODO: Make "Scene Path" lazy in 212 if (mySession.EvaluationOptions.AllowTargetInvoke) { // Only add "Scene Path" to the most derived type, not every "base" node back to Component var valueType = valueRole.ValueReference.GetValueType(options, ValueServices.ValueMetadataProvider); if (valueType.Equals(instanceType)) { var scenePathValue = GetGameObjectScenePath(valueRole, options); if (scenePathValue != null) { yield return(scenePathValue); } } } foreach (var valueEntity in base.GetChildren(valueRole, instanceType, options, dataHolder, token)) { yield return(valueEntity); } }
public override IEnumerable <IValueEntity> GetChildren(IPresentationOptions options, CancellationToken token = new CancellationToken()) { var gameObjectsArray = new SimpleValueReference <TValue>( myValueRole.CallInstanceMethod(myGetRootObjectMethod), myValueRole.ValueReference.OriginatingFrame, myValueServices.RoleFactory) .GetExactPrimaryRoleSafe <TValue, IArrayValueRole <TValue> >(options); if (gameObjectsArray == null) { yield break; } var childReferencesEnumerator = (IChildReferencesEnumerator <TValue>)gameObjectsArray; foreach (var childReference in childReferencesEnumerator.GetChildReferences()) { var childRole = childReference.AsObjectSafe(options); if (childRole == null) { continue; } var name = childRole.GetInstancePropertyReference("name", true)?.AsStringSafe(options) ?.GetString() ?? "Game Object"; yield return(new NamedReferenceDecorator <TValue>(childRole.ValueReference, name, ValueOriginKind.Property, childRole.ReifiedType.MetadataType, myValueServices.RoleFactory) .ToValue(myValueServices)); } }
private IEnumerable <IValueEntity> GetChildrenImpl(IPresentationOptions options, CancellationToken token) { // GameObject[] Scene.GetRootObjects() var gameObjectArray = new SimpleValueReference <TValue>( mySceneValueRole.CallInstanceMethod(myGetRootObjectsMethod), mySceneValueRole.ValueReference.OriginatingFrame, myValueServices.RoleFactory) .GetExactPrimaryRoleSafe <TValue, IArrayValueRole <TValue> >(options); if (gameObjectArray == null) { myLogger.Warn("Unable to retrieve GameObject array, or unexpectedly returned null"); yield break; } if (options.ClusterArrays) { var absoluteElementCount = ArrayIndexUtil.GetAbsoluteElementCount(gameObjectArray.Dimensions); foreach (var valueEntity in GetChunkedChildren(gameObjectArray, 0, absoluteElementCount, options, token)) { yield return(valueEntity); } } else { var enumerator = (IChildReferencesEnumerator <TValue>)gameObjectArray; foreach (var childReference in enumerator.GetChildReferences()) { yield return(GetElementValue(childReference, options)); } } }
private IValuePresentation GetValuePresentation(IObjectValueRole <TValue> serializedPropertyRole, SerializedPropertyKind propertyType, IPresentationOptions options, out string extraDetail) { extraDetail = null; var valueProperty = GetValueFieldName(propertyType); var valueReference = valueProperty == null ? null : serializedPropertyRole.GetInstancePropertyReference(valueProperty); if (propertyType == SerializedPropertyKind.Enum) { extraDetail = SerializedPropertyHelper.GetEnumValueIndexAsEnumName(serializedPropertyRole, valueReference, options); } else if (propertyType == SerializedPropertyKind.Character) { extraDetail = SerializedPropertyHelper.GetIntValueAsPrintableChar(valueReference, options); } else if (propertyType == SerializedPropertyKind.Integer) { var type = serializedPropertyRole.GetInstancePropertyReference("type")?.AsStringSafe(options) ?.GetString(); if (type == "char") { extraDetail = SerializedPropertyHelper.GetIntValueAsPrintableChar(valueReference, options); } } return(valueReference?.ToValue(ValueServices)?.GetValuePresentation(options)); }
public override bool IsApplicable(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder) { // Note that DebuggerDisplayObjectPresenter checks options.AllowTargetInvoke here return(myUnityOptions.ExtensionsEnabled && options.AllowDebuggerDisplayEvaluation && TryCacheDebuggerDisplay(valueRole, instanceType.GetGenericTypeDefinition(), dataHolder)); }
protected override bool IsApplicable(IMetadataTypeLite type, IPresentationOptions options, IUserDataHolder dataHolder) { // Check debugger type proxy settings to avoid recursion while rendering Raw View. See GetChildren return(myUnityOptions.ExtensionsEnabled && options.EvaluateDebuggerTypeProxy && type.Is("UnityEditor.SerializedProperty")); }
protected override IEnumerable <IValueEntity> GetChildren(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder, CancellationToken token) { yield return(new ChildrenGroup(valueRole, ValueServices, myLogger)); }
public override IEnumerable <IValueEntity> GetChildren(IPresentationOptions options, CancellationToken token = new CancellationToken()) { var frame = myGameObjectRole.ValueReference.OriginatingFrame; var componentType = myValueServices.TypeUniverse.GetReifiedType(frame, "UnityEngine.Component, UnityEngine.CoreModule") ?? myValueServices.TypeUniverse.GetReifiedType(frame, "UnityEngine.Component, UnityEngine"); if (componentType == null) { yield break; } var getComponentsMethod = myGameObjectRole.ReifiedType.MetadataType.GetMethods() .FirstOrDefault(ourGetComponentsSelector); if (getComponentsMethod == null) { yield break; } // Component[] GameObject.GetComponents(typeof(Component)) var typeObject = (IValueReference <TValue>)componentType.GetTypeObject(frame); var componentsArray = myGameObjectRole.CallInstanceMethod(getComponentsMethod, typeObject.GetValue(options)); var componentArray = new SimpleValueReference <TValue>(componentsArray, frame, myValueServices.RoleFactory) .GetExactPrimaryRoleSafe <TValue, IArrayValueRole <TValue> >(options); if (componentArray == null) { yield break; } // string UnityEditor.ObjectNames.GetInspectorTitle(UnityEngine.Object) // Returns the name of the component, formatted the same as in the Inspector. Values are also cached per // type. This obviously won't be available for standalone players, where we'll display the short type // name instead. // TODO: Support extra fallback names // Unity doesn't use the short name, but will look at the type and use GameObject.name, // MonoBehaviour.GetScriptClassName and so on. var objectNamesType = (IReifiedType <TValue>) (myValueServices.TypeUniverse.GetReifiedType(frame, "UnityEditor.ObjectNames, UnityEditor") ?? myValueServices.TypeUniverse.GetReifiedType(frame, "UnityEditor.ObjectNames, UnityEditor.CoreModule")); var getInspectorTitleMethod = objectNamesType?.MetadataType.GetMethods() .FirstOrDefault(ourGetInspectorTitleSelector); var childReferencesEnumerator = (IChildReferencesEnumerator <TValue>)componentArray; foreach (var componentReference in childReferencesEnumerator.GetChildReferences()) { var componentName = GetComponentName(componentReference, objectNamesType, getInspectorTitleMethod, frame, options, myValueServices); yield return(new NamedReferenceDecorator <TValue>(componentReference, componentName, ValueOriginKind.ArrayElement, componentType.MetadataType, myValueServices.RoleFactory) .ToValue(myValueServices)); } }
public override IValuePresentation PresentValue(IStringValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder, CancellationToken token) { // Note that ValueFlags.IsString will add the "View" link to see a string in a popup. We don't need this var text = valueRole.GetString(); return(SimplePresentation.CreateSuccess(ValuePresentationPart.Default(text), valueRole.ValueReference.DefaultFlags | ValueFlags.NoChildren, instanceType, text)); }
public override IEnumerable <IValueEntity> GetChildren(IPresentationOptions options, CancellationToken token = new CancellationToken()) { return(myLogger.CatchEvaluatorException <TValue, IEnumerable <IValueEntity> >( () => GetChildrenImpl(options), exception => myLogger.LogThrownUnityException(exception, mySerializedObjectRole.ValueReference.OriginatingFrame, myValueServices, options)) ?? EmptyList <IValueEntity> .Enumerable); }
public override IValuePresentation PresentValue(IStringValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder, CancellationToken token) { // Present the value's string as plain text, without any syntax highlighting or quote handling. Don't use // ValueFlags.IsString, as it will add an unnecessary "View" link - our text is always short var text = valueRole.GetString(); return(SimplePresentation.CreateSuccess(ValuePresentationPart.Default(text), valueRole.ValueReference.DefaultFlags | ValueFlags.NoChildren, instanceType, text)); }
public override IEnumerable <IValueEntity> GetChildren(IPresentationOptions options, CancellationToken token = new CancellationToken()) { // Eagerly enumerate the iterator to make sure we catch the exceptions correctly return(myLogger.CatchEvaluatorException <TValue, IEnumerable <IValueEntity> >( () => GetChildrenImpl(options).ToList(), exception => myLogger.LogThrownUnityException(exception, myGameObjectRole.ValueReference.OriginatingFrame, myValueServices, options)) ?? EmptyList <IValueEntity> .Enumerable); }
protected override IEnumerable <IValueEntity> GetChildren(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder, CancellationToken token) { var references = EnumerateChildren(valueRole, options, token); references = FilterChildren(references); references = SortChildren(references); return(RenderChildren(valueRole, references, options, token)); }
private IValueEntity GetGameObjectScenePath(IObjectValueRole <TValue> componentRole, IPresentationOptions options) { var gameObjectRole = Logger.CatchEvaluatorException <TValue, IObjectValueRole <TValue> >( () => componentRole.GetInstancePropertyReference("gameObject", true) ?.AsObjectSafe(options), exception => Logger.LogThrownUnityException(exception, componentRole.ValueReference.OriginatingFrame, ValueServices, options)); return(ScenePathValueHelper.GetScenePathValue(gameObjectRole, options, ValueServices, Logger)); }
protected IEnumerable <IValueReference <TValue> > EnumerateChildren([NotNull] IObjectValueRole <TValue> valueRole, IPresentationOptions options, CancellationToken token) { // This is essentially the same as ChildrenRenderingUtil.EnumerateMembersFlat and EnumerateMembersWithBaseNode // but allows us to split enumerating, sorting, and rendering into separate steps so we can also insert // filtering. return(options.FlattenHierarchy ? ChildrenRenderingUtil.CollectMembersByOverridingRules(valueRole, options, token) : GetPropertiesAndFields(valueRole)); }
public override IEnumerable <IValueEntity> GetChildren(IPresentationOptions options, CancellationToken token = new CancellationToken()) { // Keep an eye on iterators and enumeration: we need to eagerly evaluate GetChildrenImpl so we can catch // any exceptions. The return value of GetChildren is eagerly evaluated, so we're not changing any // semantics. But remember that chunked groups are lazily evaluated, and need try/catch return(myLogger.CatchEvaluatorException <TValue, IEnumerable <IValueEntity> >( () => GetChildrenImpl(options, token).ToList(), exception => myLogger.LogThrownUnityException(exception, mySerializedPropertyRole.ValueReference.OriginatingFrame, myValueServices, options)) ?? EmptyList <IValueEntity> .Enumerable); }
public override IEnumerable <IValueEntity> GetChildren(IPresentationOptions options, CancellationToken token = new CancellationToken()) { try { return(GetChildrenImpl(options, token)); } catch (Exception e) { myLogger.Error(e); return(EmptyList <IValueEntity> .Enumerable); } }
protected override IEnumerable <IValueEntity> GetChildren(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder, CancellationToken token) { // GetRootGameObjects was introduced in Unity 5.3.2 var getRootObjectsMethod = valueRole.ReifiedType.MetadataType.GetMethods() .FirstOrDefault(ourGetRootGameObjectsSelector); if (getRootObjectsMethod != null) { yield return(new GameObjectsGroup(valueRole, getRootObjectsMethod, ValueServices, myLogger)); } }
protected override IEnumerable <IValueEntity> GetChildren(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder, CancellationToken token) { // Keep an eye on iterators and enumeration: we need to eagerly evaluate GetChildrenImpl so we can catch any // exceptions. The return value of GetChildren is eagerly evaluated, so we're not changing any semantics return(Logger.CatchEvaluatorException <TValue, IEnumerable <IValueEntity> >( () => GetChildrenImpl(valueRole, instanceType, options, dataHolder, token).ToList(), exception => Logger.LogThrownUnityException(exception, valueRole.ValueReference.OriginatingFrame, ValueServices, options)) ?? base.GetChildren(valueRole, instanceType, options, dataHolder, token)); }
protected override IEnumerable <IValueEntity> GetChildren(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder, CancellationToken token) { yield return(new GameObjectComponentsGroup(valueRole, ValueServices, myLogger)); // The children of the current GameObject (as seen in Unity's Hierarchy view) are actually the children of // GameObject.transform. This should never be null var transformProperty = valueRole.GetInstancePropertyReference("transform"); if (transformProperty != null) { yield return(new GameObjectChildrenGroup(transformProperty, ValueServices)); } }
public static string GetEnumValueIndexAsEnumName <TValue>(IObjectValueRole <TValue> serializedProperty, IValueReference <TValue> enumValueIndexReference, IPresentationOptions options) where TValue : class { var primitiveValue = enumValueIndexReference.AsPrimitiveSafe(options)?.GetPrimitive(); if (primitiveValue is int enumValueIndex && serializedProperty.GetInstancePropertyReference("enumNames")?.GetPrimaryRole(options) is IArrayValueRole <TValue> enumNamesArray) { return(enumNamesArray.GetElementReference(enumValueIndex).AsStringSafe(options)?.GetString()); } return(null); }
private IEnumerable <IValueEntity> GetChildrenImpl(IPresentationOptions options, CancellationToken token) { // The children of a GameObject (as seen in Unity's Hierarchy view) are actually the children of // gameObject.transform. This will never be null. var transformRole = myGameObjectRole.GetInstancePropertyReference("transform")?.AsObjectSafe(options); if (transformRole == null) { myLogger.Warn("Unable to retrieve GameObject.transform"); yield break; } var childCount = transformRole.GetInstancePropertyReference("childCount", true) ?.AsPrimitiveSafe(options)?.GetPrimitiveSafe <int>() ?? 0; if (childCount == 0) { myLogger.Trace("No child transform, or unable to fetch childCount"); yield break; } var transformType = transformRole.ReifiedType.MetadataType.FindTypeThroughHierarchy("UnityEngine.Transform"); myGetChildMethod = transformType?.GetMethods().FirstOrDefault(ourGetChildSelector); if (myGetChildMethod == null) { myLogger.Warn("Unable to find Transform.GetChild method"); yield break; } if (options.ClusterArrays) { foreach (var valueEntity in GetChunkedChildren(transformRole, 0, childCount, options, token)) { yield return(valueEntity); } } else { for (var i = 0; i < childCount; i++) { yield return(GetElementValueAt(transformRole, i, options)); } } }
public override IEnumerable <IValueEntity> GetChildren(IPresentationOptions options, CancellationToken token = new CancellationToken()) { var transformObject = myTransformReference.AsObjectSafe(options); var childCountRole = transformObject?.GetInstancePropertyReference("childCount", true) ?.AsPrimitiveSafe(options); if (childCountRole == null) { yield break; } if (!(childCountRole.GetPrimitive() is int childCount)) { yield break; } var transformType = transformObject.ReifiedType.MetadataType.FindTypeThroughHierarchy("UnityEngine.Transform"); var getChildMethod = transformType?.GetMethods().FirstOrDefault(ourGetChildSelector); if (getChildMethod == null) { yield break; } for (int i = 0; i < childCount; i++) { var frame = myTransformReference.OriginatingFrame; var index = myServices.ValueFactory.CreatePrimitive(frame, options, i); var childTransform = new SimpleValueReference <TValue>( transformObject.CallInstanceMethod(getChildMethod, index), frame, myServices.RoleFactory) .AsObjectSafe(options); if (childTransform == null) { continue; } var name = childTransform.GetInstancePropertyReference("name", true)?.AsStringSafe(options) ?.GetString() ?? "Game Object"; yield return(new NamedReferenceDecorator <TValue>(childTransform.ValueReference, name, ValueOriginKind.Property, transformType, myServices.RoleFactory).ToValue(myServices)); } }
// Return null to allow other providers a chance. If we throw EvaluatorException, it will be presented to the // user. OperationCancelledException will be logged and we move on to the next presenter. Any other exception // will leak public override IValuePresentation PresentValue(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder, CancellationToken token) { var debuggerDisplayString = dataHolder.GetData(ourDebuggerDisplayStringKey); try { var valueReference = valueRole.ValueReference; var thisObj = valueReference.GetValue(options); var evaluationOptions = valueReference.OriginatingFrame.DebuggerSession.Options.EvaluationOptions.Apply(options); // This can throw if there are members missing, which is entirely possible when debugging on a device, // due to stripping. It will throw EvaluatorException. Anything else is logged and thrown as a new // EvaluatorException. We can also get InvalidOperationException, but only if no other evaluators can // handle the current context, which is unlikely var displayString = ExpressionEvaluators.EvaluateDisplayString(valueReference.OriginatingFrame, thisObj, debuggerDisplayString, evaluationOptions, token); var flags = valueReference.DefaultFlags; if (valueReference is CalculatedValueReferenceDecorator <TValue> reference && !reference.AllowDefaultTypePresentation) { flags |= ValueFlags.IsDefaultTypePresentation; } return(SimplePresentation.CreateSuccess( ValuePresentationPart.Default(DisplayStringUtil.EscapeString(displayString)), flags, instanceType, displayString)); } catch (Exception ex) { // Log as warning, not error - there's nothing the user can do, and we're likely to encounter this with // device builds myLogger.Warn(ex, comment: $"Unable to evaluate debugger display string for type {instanceType.GetGenericTypeDefinition().FullName}: {debuggerDisplayString}. " + "Expected behaviour on devices due to stripping"); return(null); } }