private IValueReference <TValue> GetActiveScene(IStackFrame frame) { try { var sceneManagerType = myValueServices.GetReifiedType(frame, "UnityEngine.SceneManagement.SceneManager, UnityEngine.CoreModule") ?? myValueServices.GetReifiedType(frame, "UnityEngine.SceneManagement.SceneManager, UnityEngine"); if (sceneManagerType == null) { myLogger.Warn("Unable to get typeof(SceneManager). Not a Unity project?"); return(null); } var getActiveSceneMethod = sceneManagerType.MetadataType.GetMethods() .FirstOrDefault(m => m.IsStatic && m.Parameters.Length == 0 && m.Name == "GetActiveScene"); if (getActiveSceneMethod == null) { myLogger.Warn("Unable to find SceneManager.GetActiveScene"); return(null); } var activeScene = sceneManagerType.CallStaticMethod(frame, mySession.EvaluationOptions, getActiveSceneMethod); if (activeScene == null) { myLogger.Warn("Unexpected response: SceneManager.GetActiveScene() == null"); return(null); } // Don't show type presentation. We know it's a scene, the clue's in the name return(new SimpleValueReference <TValue>(activeScene, sceneManagerType.MetadataType, "Active scene", ValueOriginKind.Property, ValueFlags.None | ValueFlags.IsReadOnly | ValueFlags.IsDefaultTypePresentation, frame, myValueServices.RoleFactory)); } catch (Exception e) { myLogger.LogException(e); return(null); } }
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(IPresentationOptions 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); yield return(new NamedReferenceDecorator <TValue>(componentReference, componentName, ValueOriginKind.Property, ValueFlags.None | ValueFlags.IsReadOnly, componentType.MetadataType, myValueServices.RoleFactory, isNameFromValue) .ToValue(myValueServices)); } }