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 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); }
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)); } }
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 string GetComponentName(IValueReference <TValue> componentValue, [CanBeNull] IReifiedType <TValue> objectNamesType, [CanBeNull] IMetadataMethodLite getInspectorTitleMethod, IStackFrame frame, IValueFetchOptions options, IValueServicesFacade <TValue> services) { if (objectNamesType != null && getInspectorTitleMethod != null) { try { var inspectorTitle = objectNamesType.CallStaticMethod(frame, options, getInspectorTitleMethod, componentValue.GetValue(options)); var stringValueRole = new SimpleValueReference <TValue>(inspectorTitle, frame, services.RoleFactory) .AsStringSafe(options); if (stringValueRole != null) { return(stringValueRole.GetString()); } } catch (Exception e) { myLogger.Error(e, "Unable to fetch object names for {0}", componentValue); } } return(componentValue.GetPrimaryRole(options).ReifiedType.MetadataType.ShortName); }
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 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")); } }
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)); } }
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 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)); }
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)); } }
public static string GetThrownExceptionMessage <TValue>(EvaluatorExceptionThrownException <TValue> exception, IStackFrame frame, IValueServicesFacade <TValue> valueServices, IValueFetchOptions valueFetchOptions, ILogger logger) where TValue : class { try { var reference = new SimpleValueReference <TValue>(exception.Exception, frame, valueServices.RoleFactory); return(reference.AsObjectSafe(valueFetchOptions) ?.GetInstancePropertyReference("Message", true) ?.AsStringSafe(valueFetchOptions)?.GetString()); } catch (Exception e) { // Argh! Exception thrown while trying to get information about a thrown exception! logger.LogExceptionSilently(e); return(null); } }
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); if (gameObject == null) { return(new ErrorValue("Game Object", "Unable to retrieve child game object")); } 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)); }
private bool TryInvokeNext(IObjectValueRole <TValue> serializedPropertyRole, IMetadataMethodLite nextMethod, TValue boolArg, IValueFetchOptions options, out bool returnValue) { returnValue = false; var returnValueRole = new SimpleValueReference <TValue>( serializedPropertyRole.CallInstanceMethod(nextMethod, boolArg), mySerializedPropertyRole.ValueReference.OriginatingFrame, myValueServices.RoleFactory) .AsPrimitiveSafe(options); if (returnValueRole == null) { myLogger.Warn("Unable to call Next on serializedProperty"); return(false); } returnValue = returnValueRole.GetPrimitive <bool>(); return(true); }
private string GetComponentName(IValueReference <TValue> componentValue, [CanBeNull] IReifiedType <TValue> objectNamesType, [CanBeNull] IMetadataMethodLite getInspectorTitleMethod, IStackFrame frame, IValueFetchOptions options, IValueServicesFacade <TValue> services, out bool isNameFromValue) { if (objectNamesType != null && getInspectorTitleMethod != null) { try { var inspectorTitle = objectNamesType.CallStaticMethod(frame, options, getInspectorTitleMethod, componentValue.GetValue(options)); var stringValueRole = new SimpleValueReference <TValue>(inspectorTitle, frame, services.RoleFactory) .AsStringSafe(options); if (stringValueRole != null) { isNameFromValue = true; return(stringValueRole.GetString()); } } catch (EvaluatorAbortedException e) { myLogger.LogExceptionSilently(e); } catch (Exception e) { myLogger.Warn(e, ExceptionOrigin.Algorithmic, $"Unable to fetch object names for {componentValue}"); } } isNameFromValue = false; return(componentValue.GetPrimaryRole(options).ReifiedType.MetadataType.ShortName); }
public static IValueEntity GetScenePathValue <TValue>([CanBeNull] IObjectValueRole <TValue> gameObjectRole, IPresentationOptions options, IValueServicesFacade <TValue> valueServices, ILogger logger) where TValue : class { if (gameObjectRole == null) { return(null); } return(logger.CatchEvaluatorException <TValue, IValueEntity>(() => { // Only available in the editor. Not available for players, where we'll display nothing. // TODO: Hand roll this for players. Simply follow transform.parent // However, this will obviously be more expensive to calculate var frame = gameObjectRole.ValueReference.OriginatingFrame; var animationUtilityType = valueServices.GetReifiedType(frame, "UnityEditor.AnimationUtility, UnityEditor") ?? valueServices.GetReifiedType(frame, "UnityEditor.AnimationUtility, UnityEditor.CoreModule"); var method = animationUtilityType?.MetadataType.GetMethods() .FirstOrDefault(ourCalculateTransformPathSelector); if (method == null) { logger.Trace( "Unable to get metadata for AnimationUtility.CalculateTransformPath method. Is this a player?"); return null; } var targetTransformReference = gameObjectRole.GetInstancePropertyReference("transform"); var targetTransformRole = targetTransformReference?.AsObjectSafe(options); // Search in bases - transform might be a RectTransform or a Transform, and root is defined on Transform var rootTransformReference = targetTransformRole?.GetInstancePropertyReference("root", true); var rootTransformRole = rootTransformReference?.AsObjectSafe(options); if (targetTransformRole == null || rootTransformRole == null) { logger.Warn("Unable to evaluate gameObject.transform and/or gameObject.transform.root or values are null."); return null; } var rootTransformName = rootTransformRole.GetInstancePropertyReference("name", true) ?.AsStringSafe(options)?.GetString() ?? ""; var pathValue = animationUtilityType.CallStaticMethod(frame, options, method, targetTransformReference.GetValue(options), rootTransformReference.GetValue(options)); var path = new SimpleValueReference <TValue>(pathValue, frame, valueServices.RoleFactory) .AsStringSafe(options)?.GetString(); if (path == null) { // We expect empty string at least logger.Warn("Unexpected null returned from AnimationUtility.CalculateTransformPath"); return null; } var fullPath = path.IsNullOrEmpty() ? rootTransformName : rootTransformName + "/" + path; var fullPathValue = valueServices.ValueFactory.CreateString(frame, options, fullPath); // Don't show type presentation. This is informational, rather than an actual property var simpleReference = new SimpleValueReference <TValue>(fullPathValue, null, "Scene path", ValueOriginKind.Property, ValueFlags.None | ValueFlags.IsReadOnly | ValueFlags.IsDefaultTypePresentation, frame, valueServices.RoleFactory); // Wrap the simple reference - the default StringValuePresenter will display the simple reference as a // string property, with syntax colouring, quotes and type name. Our TextValuePresenter will handle the // TextValueReference and use the flags we've set return new TextValueReference <TValue>(simpleReference, valueServices.RoleFactory).ToValue( valueServices); }, exception => logger.LogThrownUnityException(exception, gameObjectRole.ValueReference.OriginatingFrame, valueServices, options))); }
private IEnumerable <IValueEntity> GetChildrenImpl(IValueFetchOptions options) { var frame = myGameObjectRole.ValueReference.OriginatingFrame; var componentType = myValueServices.GetReifiedType(frame, "UnityEngine.Component, UnityEngine.CoreModule") ?? myValueServices.GetReifiedType(frame, "UnityEngine.Component, UnityEngine"); if (componentType == null) { myLogger.Warn("Unable to find UnityEngine.Component"); yield break; } var getComponentsMethod = myGameObjectRole.ReifiedType.MetadataType.GetMethods() .FirstOrDefault(ourGetComponentsSelector); if (getComponentsMethod == null) { myLogger.Warn("Unable to find UnityEngine.GameObject.GetComponents method"); yield break; } // Call 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) { myLogger.Warn("Cannot get return value of GameObject.GetComponents or method returned 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 = myValueServices.GetReifiedType(frame, "UnityEditor.ObjectNames, UnityEditor") ?? myValueServices.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, out var isNameFromValue); // Tell the value presenter to hide the name field, if we're using it for the key. Also hide the // default type presentation - we know it's a Component, it's under a group called "Components" yield return(new CalculatedValueReferenceDecorator <TValue>(componentReference, myValueServices.RoleFactory, componentName, !isNameFromValue, false).ToValue(myValueServices)); } }