Maze / Library /PackageCache /com.unity.visualscripting@1.8.0 /Runtime /VisualScripting.Flow /Framework /Codebase /Expose.cs
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Reflection; | |
| using UnityEngine; | |
| namespace Unity.VisualScripting | |
| { | |
| /// <summary> | |
| /// Exposes all members of the type. | |
| /// </summary> | |
| [] | |
| public sealed class Expose : Unit, IAotStubbable | |
| { | |
| public Expose() : base() { } | |
| public Expose(Type type) : base() | |
| { | |
| this.type = type; | |
| } | |
| [] | |
| public Type type { get; set; } | |
| [] | |
| public bool instance { get; set; } = true; | |
| [] | |
| public bool @static { get; set; } = true; | |
| /// <summary> | |
| /// The instance of the exposed type. | |
| /// </summary> | |
| [] | |
| [] | |
| [] | |
| public ValueInput target { get; private set; } | |
| [] | |
| public Dictionary<ValueOutput, Member> members { get; private set; } | |
| public override bool canDefine => type != null; | |
| public override IEnumerable<object> GetAotStubs(HashSet<object> visited) | |
| { | |
| if (members != null) | |
| { | |
| foreach (var member in members.Values) | |
| { | |
| if (member != null && member.isReflected) | |
| { | |
| yield return member.info; | |
| } | |
| } | |
| } | |
| } | |
| protected override void Definition() | |
| { | |
| members = new Dictionary<ValueOutput, Member>(); | |
| var requiresTarget = false; | |
| foreach (var member in type.GetMembers() | |
| .Where(m => m is FieldInfo || m is PropertyInfo) | |
| .Select(m => m.ToManipulator(type)) | |
| .DistinctBy(m => m.name) // To account for "new" duplicates | |
| .Where(Include) | |
| .OrderBy(m => m.requiresTarget ? 0 : 1) | |
| .ThenBy(m => m.order)) | |
| { | |
| var memberPort = ValueOutput(member.type, member.name, (flow) => GetValue(flow, member)); | |
| if (member.isPredictable) | |
| { | |
| memberPort.Predictable(); | |
| } | |
| members.Add(memberPort, member); | |
| if (member.requiresTarget) | |
| { | |
| requiresTarget = true; | |
| } | |
| } | |
| if (requiresTarget) | |
| { | |
| target = ValueInput(type, nameof(target)).NullMeansSelf(); | |
| target.SetDefaultValue(type.PseudoDefault()); | |
| foreach (var member in members.Keys) | |
| { | |
| if (members[member].requiresTarget) | |
| { | |
| Requirement(target, member); | |
| } | |
| } | |
| } | |
| } | |
| private bool Include(Member member) | |
| { | |
| if (!instance && member.requiresTarget) | |
| { | |
| return false; | |
| } | |
| if (!@static && !member.requiresTarget) | |
| { | |
| return false; | |
| } | |
| if (!member.isPubliclyGettable) | |
| { | |
| return false; | |
| } | |
| if (member.info.HasAttribute<ObsoleteAttribute>()) | |
| { | |
| return false; | |
| } | |
| if (member.isIndexer) | |
| { | |
| return false; | |
| } | |
| // Pesky edit-mode only accessor that is only available in the editor, | |
| // yet isn't marked by any special attribute to indicate it. | |
| if (member.name == "runInEditMode" && member.declaringType == typeof(MonoBehaviour)) | |
| { | |
| return false; | |
| } | |
| return true; | |
| } | |
| private object GetValue(Flow flow, Member member) | |
| { | |
| var target = member.requiresTarget ? flow.GetValue(this.target, member.targetType) : null; | |
| return member.Get(target); | |
| } | |
| } | |
| } | |