UnityMember.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. using System;
  2. using UnityEngine;
  3. using UnityObject = UnityEngine.Object;
  4. namespace Chronos.Reflection
  5. {
  6. [Serializable]
  7. public abstract class UnityMember
  8. {
  9. [SerializeField]
  10. private UnityObject _target;
  11. /// <summary>
  12. /// The object containing the member.
  13. /// </summary>
  14. public UnityObject target
  15. {
  16. get { return _target; }
  17. set { _target = value; isTargeted = false; }
  18. }
  19. [SerializeField]
  20. private string _component;
  21. /// <summary>
  22. /// The name of the component containing the member, if the target is a GameObject.
  23. /// </summary>
  24. public string component
  25. {
  26. get { return _component; }
  27. set { _component = value; isTargeted = false; isReflected = false; }
  28. }
  29. [SerializeField]
  30. private string _name;
  31. /// <summary>
  32. /// The name of the member.
  33. /// </summary>
  34. public string name
  35. {
  36. get { return _name; }
  37. set { _name = value; isReflected = false; }
  38. }
  39. /// <summary>
  40. /// Indicates whether the reflection target has been found and cached.
  41. /// </summary>
  42. protected bool isTargeted { get; private set; }
  43. /// <summary>
  44. /// Indicates whether the reflection data has been found and cached.
  45. /// </summary>
  46. public bool isReflected { get; protected set; }
  47. /// <summary>
  48. /// Indicates whether the member has been properly assigned.
  49. /// </summary>
  50. public bool isAssigned
  51. {
  52. get
  53. {
  54. return target != null && !string.IsNullOrEmpty(name);
  55. }
  56. }
  57. /// <summary>
  58. /// The object on which to perform reflection.
  59. /// For GameObjects and Component targets, this is the component of type <see cref="UnityMember.component"/> or the object itself if null.
  60. /// For ScriptableObjects targets, this is the object itself.
  61. /// Other Unity Objects are not supported.
  62. /// </summary>
  63. protected UnityObject reflectionTarget { get; private set; }
  64. #region Constructors
  65. public UnityMember() { }
  66. public UnityMember(string name)
  67. {
  68. this.name = name;
  69. }
  70. public UnityMember(string name, UnityObject target)
  71. {
  72. this.name = name;
  73. this.target = target;
  74. Reflect();
  75. }
  76. public UnityMember(string component, string name)
  77. {
  78. this.component = component;
  79. this.name = name;
  80. }
  81. public UnityMember(string component, string name, UnityObject target)
  82. {
  83. this.component = component;
  84. this.name = name;
  85. this.target = target;
  86. Reflect();
  87. }
  88. #endregion
  89. /// <summary>
  90. /// Gathers and caches the reflection target for the member.
  91. /// </summary>
  92. protected void Target()
  93. {
  94. if (target == null)
  95. {
  96. throw new NullReferenceException("Target has not been specified.");
  97. }
  98. GameObject targetAsGameObject = target as GameObject;
  99. Component targetAsComponent = target as Component;
  100. if (targetAsGameObject != null || targetAsComponent != null)
  101. {
  102. // The target is a GameObject or a Component.
  103. if (!string.IsNullOrEmpty(component))
  104. {
  105. // If a component is specified, look for it on the target.
  106. Component componentObject;
  107. if (targetAsGameObject != null)
  108. {
  109. componentObject = targetAsGameObject.GetComponent(component);
  110. }
  111. else // if (targetAsComponent != null)
  112. {
  113. componentObject = targetAsComponent.GetComponent(component);
  114. }
  115. if (componentObject == null)
  116. {
  117. throw new UnityReflectionException(string.Format("Target object does not contain a component of type '{0}'.", component));
  118. }
  119. reflectionTarget = componentObject;
  120. return;
  121. }
  122. else
  123. {
  124. // Otherwise, return the GameObject itself.
  125. if (targetAsGameObject != null)
  126. {
  127. reflectionTarget = targetAsGameObject;
  128. }
  129. else // if (targetAsComponent != null)
  130. {
  131. reflectionTarget = targetAsComponent.gameObject;
  132. }
  133. return;
  134. }
  135. }
  136. ScriptableObject scriptableObject = target as ScriptableObject;
  137. if (scriptableObject != null)
  138. {
  139. // The real target is directly the ScriptableObject target.
  140. reflectionTarget = scriptableObject;
  141. return;
  142. }
  143. throw new UnityReflectionException("Target should be a GameObject, a Component or a ScriptableObject.");
  144. }
  145. /// <summary>
  146. /// Gathers and caches the reflection data for the member.
  147. /// </summary>
  148. public abstract void Reflect();
  149. /// <summary>
  150. /// Gathers the reflection data if it is not alreadypresent.
  151. /// </summary>
  152. public void EnsureReflected()
  153. {
  154. if (!isReflected)
  155. {
  156. Reflect();
  157. }
  158. }
  159. /// <summary>
  160. /// Gathers the reflection target if it is not already present.
  161. /// </summary>
  162. public void EnsureTargeted()
  163. {
  164. if (!isTargeted)
  165. {
  166. Target();
  167. }
  168. }
  169. /// <summary>
  170. /// Asserts that the member has been properly assigned.
  171. /// </summary>
  172. public void EnsureAssigned()
  173. {
  174. if (!isAssigned)
  175. {
  176. throw new UnityReflectionException("Member hasn't been properly assigned.");
  177. }
  178. }
  179. public virtual bool Corresponds(UnityMember other)
  180. {
  181. return
  182. (other != null || !this.isAssigned) &&
  183. this.target == other.target &&
  184. this.component == other.component &&
  185. this.name == other.name;
  186. }
  187. }
  188. }