protected override IValue GetElementValueAt(IObjectValueRole <TValue> collection, int index, IValueFetchOptions options) { var name = $"[{index}]"; try { var frame = mySerializedPropertyRole.ValueReference.OriginatingFrame; var indexValue = myValueServices.ValueFactory.CreatePrimitive(frame, options, index); var childSerializedPropertyValue = collection.CallInstanceMethod(myGetElementMethod, indexValue); var valueReference = new SimpleValueReference <TValue>(childSerializedPropertyValue, mySerializedPropertyRole.ReifiedType.MetadataType, name, ValueOriginKind.ArrayElement, ValueFlags.None | ValueFlags.IsReadOnly, frame, myValueServices.RoleFactory); // Tell the value presenter to hide the name, because it's always "data" (DefaultName is the key name) // Also hide the type presentation - they can only ever be SerializedProperty instances return(new CalculatedValueReferenceDecorator <TValue>(valueReference, myValueServices.RoleFactory, valueReference.DefaultName, false, false).ToValue(myValueServices)); } catch (Exception e) { // We must always return a value, as we're effectively showing the contents of an array here. We're // possibly also being evaluated lazily, thanks to chunked arrays, so can't rely on the caller // catching exceptions. myLogger.LogExceptionSilently(e); return(myValueServices.ValueRenderers.GetValueStubForException(e, name, collection.ValueReference.OriginatingFrame) as IValue ?? new ErrorValue(name, "Unable to retrieve child serialized property")); } }
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 bool IsApplicable(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder) { return(myUnityOptions.ExtensionsEnabled && instanceType.Is("UnityEditor.SerializedProperty")); }
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 IValue GetElementValueAt(IObjectValueRole <TValue> collection, int index, IValueFetchOptions options) { try { var frame = myGameObjectRole.ValueReference.OriginatingFrame; var indexValue = myValueServices.ValueFactory.CreatePrimitive(frame, options, index); var childTransformValue = collection.CallInstanceMethod(myGetChildMethod, indexValue); var childTransform = new SimpleValueReference <TValue>(childTransformValue, frame, myValueServices.RoleFactory).AsObjectSafe(options); var gameObject = childTransform?.GetInstancePropertyReference("gameObject", true) ?.AsObjectSafe(options); if (gameObject == null) { return(new ErrorValue("Game Object", "Unable to find child gameObject, or value is null")); } var name = gameObject.GetInstancePropertyReference("name", true)?.AsStringSafe(options) ?.GetString() ?? "Game Object"; // Tell the value presenter to not show the name field, we're already showing it as the key. Also don't // show the type - a GameObject's child can only be a GameObject return(new CalculatedValueReferenceDecorator <TValue>(gameObject.ValueReference, myValueServices.RoleFactory, name, false, false).ToValue(myValueServices)); } catch (Exception e) { // We must always return a value, as we're effectively showing the contents of an array here. We're // possibly also being evaluated lazily, thanks to chunked arrays, so can't rely on the caller // catching exceptions. myLogger.LogExceptionSilently(e); return(myValueServices.ValueRenderers.GetValueStubForException(e, "Game Object", collection.ValueReference.OriginatingFrame) as IValue ?? new ErrorValue("Game Object", "Unable to retrieve child game object")); } }
private bool TryCopySerializedProperty(IObjectValueRole <TValue> serializedPropertyRole, IValueFetchOptions options, out IObjectValueRole <TValue> copiedSerializedPropertyRole) { copiedSerializedPropertyRole = null; // Get a copy of the property, so we can call Next(true) without updating the current instance var copyMethod = MetadataTypeLiteEx.LookupInstanceMethodSafe( mySerializedPropertyRole.ReifiedType.MetadataType, MethodSelectors.SerializedProperty_Copy, false); if (copyMethod == null) { myLogger.Warn("Cannot find Copy method on SerializedProperty"); return(false); } // CallInstanceMethod always returns not null (VoidValue if it fails) copiedSerializedPropertyRole = new SimpleValueReference <TValue>( serializedPropertyRole.CallInstanceMethod(copyMethod), mySerializedPropertyRole.ValueReference.OriginatingFrame, myValueServices.RoleFactory) .AsObjectSafe(options); if (copiedSerializedPropertyRole == null) { myLogger.Warn("Unable to Copy serializedProperty"); return(false); } return(true); }
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); } }
private bool TryInvokeGetIterator(IObjectValueRole <TValue> serializedObjectRole, IValueFetchOptions options, out IObjectValueRole <TValue> returnedSerializedPropertyRole) { returnedSerializedPropertyRole = null; var method = MetadataTypeLiteEx.LookupInstanceMethodSafe(serializedObjectRole.ReifiedType.MetadataType, MethodSelectors.SerializedObject_GetIterator, false); if (method == null) { myLogger.Warn("Cannot find GetIterator method on SerializedObject"); return(false); } returnedSerializedPropertyRole = new SimpleValueReference <TValue>( serializedObjectRole.CallInstanceMethod(method), serializedObjectRole.ValueReference.OriginatingFrame, myValueServices.RoleFactory) .AsObjectSafe(options); if (returnedSerializedPropertyRole == null) { myLogger.Warn("Unable to invoke GetIterator"); return(false); } return(true); }
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) { return(options.FlattenHierarchy ? EnumerateMembersFlat(valueRole, options, token, ValueServices) : EnumerateMembersWithBaseNode(valueRole, options, token, ValueServices)); }
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)); }
private bool TryCacheDebuggerDisplay(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IUserDataHolder userDataHolder) { // Special case. Replace with a second dictionary or whatever if we need to handle more types if (valueRole.ValueReference is NamedReferenceDecorator <TValue> reference && reference.IsNameFromValue && instanceType.FullName == "UnityEngine.GameObject") { userDataHolder.PutData(ourDebuggerDisplayStringKey, GameObjectDebuggerDisplayStringWithoutName); return(true); } // DebuggerDisplayAttribute is inherited. This is important for applying a debug string on Behaviour, and // having it used in custom MonoBehaviour classes var current = instanceType; while (current != null) { if (myDebuggerDisplayValues.TryGetValue(current.GetGenericTypeDefinition().FullName, out var displayString)) { userDataHolder.PutData(ourDebuggerDisplayStringKey, displayString); return(true); } current = current.BaseType; } return(false); }
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)); }
public GameObjectChildrenGroup(IObjectValueRole <TValue> gameObjectRole, IValueServicesFacade <TValue> valueServices, ILogger logger) : base("Children") { myGameObjectRole = gameObjectRole; myValueServices = valueServices; myLogger = logger; }
public GameObjectsGroup(IObjectValueRole <TValue> valueRole, IMetadataMethodLite getRootObjectMethod, IValueServicesFacade <TValue> valueServices) : base("Game Objects") { myValueRole = valueRole; myGetRootObjectMethod = getRootObjectMethod; myValueServices = valueServices; }
protected override IEnumerable <IValueEntity> GetChildren(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType, IPresentationOptions options, IUserDataHolder dataHolder, CancellationToken token) { yield return(new ChildrenGroup(valueRole, ValueServices, myLogger)); }
public ChildrenGroup(IObjectValueRole <TValue> serializedObjectRole, IValueServicesFacade <TValue> valueServices, ILogger logger) : base("Serialized Properties") { mySerializedObjectRole = serializedObjectRole; myValueServices = valueServices; myLogger = logger; }
public GameObjectsGroup(IObjectValueRole <TValue> sceneValueRole, IMetadataMethodLite getRootObjectsMethod, IValueServicesFacade <TValue> valueServices, ILogger logger) : base("Game objects") { mySceneValueRole = sceneValueRole; myGetRootObjectsMethod = getRootObjectsMethod; myValueServices = valueServices; myLogger = 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)); }
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 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 = componentRole.GetInstancePropertyReference("gameObject", true)?.AsObjectSafe(options); if (gameObjectRole == null) { return(null); } return(ScenePathValueHelper.GetScenePathValue(gameObjectRole, options, ValueServices, myLogger)); }
public ArrayElementsGroup(IObjectValueRole <TValue> serializedPropertyRole, int arraySize, MethodSelector getMethodElementSelector, IValueServicesFacade <TValue> valueServices, ILogger logger) : base($"[0..{arraySize - 1}]") { mySerializedPropertyRole = serializedPropertyRole; myArraySize = arraySize; myGetMethodElementSelector = getMethodElementSelector; myValueServices = valueServices; myLogger = logger; }
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 IValue GetElementValueAt(IObjectValueRole <TValue> collection, int index, IValueFetchOptions options) { var frame = mySerializedPropertyRole.ValueReference.OriginatingFrame; var indexValue = myValueServices.ValueFactory.CreatePrimitive(frame, options, index); var childSerializedPropertyValue = collection.CallInstanceMethod(myGetElementMethod, indexValue); var valueReference = new SimpleValueReference <TValue>(childSerializedPropertyValue, mySerializedPropertyRole.ReifiedType.MetadataType, $"[{index}]", ValueOriginKind.ArrayElement, ValueFlags.None | ValueFlags.IsReadOnly, frame, myValueServices.RoleFactory); // Tell the value presenter to hide the name, because it's always "data" (DefaultName is the key name) // Also hide the type presentation - they can only ever be SerializedProperty instances return(new CalculatedValueReferenceDecorator <TValue>(valueReference, myValueServices.RoleFactory, valueReference.DefaultName, false, false).ToValue(myValueServices)); }
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)); }
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); }
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 bool TryEvaluatePrimitiveProperty <TValue, TPrimitive>(IObjectValueRole <TValue> valueRole, string property, IValueFetchOptions options, out TPrimitive value) where TValue : class where TPrimitive : struct { value = default; var primitiveValueRole = valueRole.GetInstancePropertyReference(property)?.AsPrimitiveSafe(options); if (!(primitiveValueRole?.GetPrimitive() is TPrimitive primitive)) { return(false); } value = primitive; return(true); }
protected override IValue GetElementValueAt(IObjectValueRole <TValue> collection, int index, IValueFetchOptions options) { var frame = myGameObjectRole.ValueReference.OriginatingFrame; var indexValue = myValueServices.ValueFactory.CreatePrimitive(frame, options, index); var childTransformValue = collection.CallInstanceMethod(myGetChildMethod, indexValue); var childTransform = new SimpleValueReference <TValue>(childTransformValue, frame, myValueServices.RoleFactory).AsObjectSafe(options); var gameObject = childTransform?.GetInstancePropertyReference("gameObject", true) ?.AsObjectSafe(options); var name = gameObject?.GetInstancePropertyReference("name", true)?.AsStringSafe(options) ?.GetString() ?? "Game Object"; return(new NamedReferenceDecorator <TValue>(gameObject.ValueReference, name, ValueOriginKind.Property, ValueFlags.None | ValueFlags.IsReadOnly, myGameObjectRole.ReifiedType.MetadataType, myValueServices.RoleFactory, true) .ToValue(myValueServices)); }