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));
                    }
                }
            }
Exemple #2
0
 public override bool IsApplicable(IValueRole <TValue> role,
                                   IMetadataTypeLite instanceType,
                                   IPresentationOptions options,
                                   IUserDataHolder dataHolder)
 {
     return(myUnityOptions.ExtensionsEnabled && role.ValueReference is ExtraDetailValueReferenceDecorator <TValue>);
 }
Exemple #3
0
 public override bool IsApplicable(IObjectValueRole <TValue> valueRole,
                                   IMetadataTypeLite instanceType,
                                   IPresentationOptions options,
                                   IUserDataHolder dataHolder)
 {
     return(myUnityOptions.ExtensionsEnabled && instanceType.Is("UnityEditor.SerializedProperty"));
 }
Exemple #4
0
        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);
            }
        }
Exemple #5
0
        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);
            }
        }
Exemple #7
0
        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);
            }
        }
Exemple #8
0
            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));
                    }
                }
            }
Exemple #10
0
        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"));
 }
Exemple #13
0
 protected override IEnumerable <IValueEntity> GetChildren(IObjectValueRole <TValue> valueRole,
                                                           IMetadataTypeLite instanceType,
                                                           IPresentationOptions options,
                                                           IUserDataHolder dataHolder,
                                                           CancellationToken token)
 {
     yield return(new ChildrenGroup(valueRole, ValueServices, myLogger));
 }
Exemple #14
0
            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));
                }
            }
Exemple #15
0
        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));
        }
Exemple #16
0
 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));
        }
Exemple #18
0
 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));
        }
Exemple #20
0
        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));
 }
Exemple #26
0
        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));
            }
        }
Exemple #27
0
        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));
                    }
                }
            }
Exemple #29
0
            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);
            }
        }