No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Expose.cs 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using UnityEngine;
  6. namespace Unity.VisualScripting
  7. {
  8. /// <summary>
  9. /// Exposes all members of the type.
  10. /// </summary>
  11. [SpecialUnit]
  12. public sealed class Expose : Unit, IAotStubbable
  13. {
  14. public Expose() : base() { }
  15. public Expose(Type type) : base()
  16. {
  17. this.type = type;
  18. }
  19. [Serialize, Inspectable, TypeFilter(Enums = false)]
  20. public Type type { get; set; }
  21. [Serialize, Inspectable, UnitHeaderInspectable("Instance"), InspectorToggleLeft]
  22. public bool instance { get; set; } = true;
  23. [Serialize, Inspectable, UnitHeaderInspectable("Static"), InspectorToggleLeft]
  24. public bool @static { get; set; } = true;
  25. /// <summary>
  26. /// The instance of the exposed type.
  27. /// </summary>
  28. [DoNotSerialize]
  29. [PortLabelHidden]
  30. [NullMeansSelf]
  31. public ValueInput target { get; private set; }
  32. [DoNotSerialize]
  33. public Dictionary<ValueOutput, Member> members { get; private set; }
  34. public override bool canDefine => type != null;
  35. public override IEnumerable<object> GetAotStubs(HashSet<object> visited)
  36. {
  37. if (members != null)
  38. {
  39. foreach (var member in members.Values)
  40. {
  41. if (member != null && member.isReflected)
  42. {
  43. yield return member.info;
  44. }
  45. }
  46. }
  47. }
  48. protected override void Definition()
  49. {
  50. members = new Dictionary<ValueOutput, Member>();
  51. var requiresTarget = false;
  52. foreach (var member in type.GetMembers()
  53. .Where(m => m is FieldInfo || m is PropertyInfo)
  54. .Select(m => m.ToManipulator(type))
  55. .DistinctBy(m => m.name) // To account for "new" duplicates
  56. .Where(Include)
  57. .OrderBy(m => m.requiresTarget ? 0 : 1)
  58. .ThenBy(m => m.order))
  59. {
  60. var memberPort = ValueOutput(member.type, member.name, (flow) => GetValue(flow, member));
  61. if (member.isPredictable)
  62. {
  63. memberPort.Predictable();
  64. }
  65. members.Add(memberPort, member);
  66. if (member.requiresTarget)
  67. {
  68. requiresTarget = true;
  69. }
  70. }
  71. if (requiresTarget)
  72. {
  73. target = ValueInput(type, nameof(target)).NullMeansSelf();
  74. target.SetDefaultValue(type.PseudoDefault());
  75. foreach (var member in members.Keys)
  76. {
  77. if (members[member].requiresTarget)
  78. {
  79. Requirement(target, member);
  80. }
  81. }
  82. }
  83. }
  84. private bool Include(Member member)
  85. {
  86. if (!instance && member.requiresTarget)
  87. {
  88. return false;
  89. }
  90. if (!@static && !member.requiresTarget)
  91. {
  92. return false;
  93. }
  94. if (!member.isPubliclyGettable)
  95. {
  96. return false;
  97. }
  98. if (member.info.HasAttribute<ObsoleteAttribute>())
  99. {
  100. return false;
  101. }
  102. if (member.isIndexer)
  103. {
  104. return false;
  105. }
  106. // Pesky edit-mode only accessor that is only available in the editor,
  107. // yet isn't marked by any special attribute to indicate it.
  108. if (member.name == "runInEditMode" && member.declaringType == typeof(MonoBehaviour))
  109. {
  110. return false;
  111. }
  112. return true;
  113. }
  114. private object GetValue(Flow flow, Member member)
  115. {
  116. var target = member.requiresTarget ? flow.GetValue(this.target, member.targetType) : null;
  117. return member.Get(target);
  118. }
  119. }
  120. }