Нема описа
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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using Unity.Profiling;
  4. using UnityEngine.Scripting.APIUpdating;
  5. using UnityEngine.U2D.Animation;
  6. using UnityEngine.U2D.Common;
  7. namespace UnityEngine.U2D.IK
  8. {
  9. /// <summary>
  10. /// Component responsible for managing and updating 2D IK Solvers.
  11. /// </summary>
  12. [DefaultExecutionOrder(UpdateOrder.ikUpdateOrder)]
  13. [MovedFrom("UnityEngine.Experimental.U2D.IK")]
  14. [IconAttribute(IconUtility.IconPath + "Animation.IKManager.png")]
  15. [ExecuteInEditMode]
  16. public partial class IKManager2D : MonoBehaviour, IPreviewable
  17. {
  18. #if UNITY_EDITOR
  19. internal static event System.Action<IKManager2D> onEnabledEditor;
  20. internal static event System.Action<IKManager2D> onDisabledEditor;
  21. #endif
  22. [SerializeField]
  23. List<Solver2D> m_Solvers = new List<Solver2D>();
  24. [SerializeField]
  25. [Range(0f, 1f)]
  26. float m_Weight = 1f;
  27. [SerializeField]
  28. bool m_AlwaysUpdate = true;
  29. bool m_CullingEnabled;
  30. BaseCullingStrategy m_CullingStrategy;
  31. internal BaseCullingStrategy GetCullingStrategy() => m_CullingStrategy;
  32. /// <summary>
  33. /// Get and set the weight for solvers.
  34. /// </summary>
  35. public float weight
  36. {
  37. get => m_Weight;
  38. set => m_Weight = Mathf.Clamp01(value);
  39. }
  40. /// <summary>
  41. /// Get the Solvers that are managed by this manager.
  42. /// </summary>
  43. public List<Solver2D> solvers => m_Solvers;
  44. int[] m_TransformIdCache;
  45. /// <summary>
  46. /// Solvers are always updated even if the underlying Sprite Skins are not visible.
  47. /// </summary>
  48. public bool alwaysUpdate
  49. {
  50. get => m_AlwaysUpdate;
  51. set
  52. {
  53. m_AlwaysUpdate = value;
  54. ToggleCulling(!m_AlwaysUpdate);
  55. }
  56. }
  57. void OnEnable()
  58. {
  59. ToggleCulling(!m_AlwaysUpdate);
  60. #if UNITY_EDITOR
  61. onEnabledEditor?.Invoke(this);
  62. #endif
  63. }
  64. void OnDisable()
  65. {
  66. ToggleCulling(false);
  67. #if UNITY_EDITOR
  68. onDisabledEditor?.Invoke(this);
  69. #endif
  70. }
  71. void ToggleCulling(bool enableCulling)
  72. {
  73. if(m_CullingStrategy != null && m_CullingEnabled == enableCulling)
  74. return;
  75. m_CullingEnabled = enableCulling;
  76. m_CullingStrategy?.RemoveRequestingObject(this);
  77. if (m_CullingEnabled)
  78. m_CullingStrategy = CullingManager.instance.GetCullingStrategy<SpriteSkinVisibilityCullingStrategy>();
  79. else
  80. m_CullingStrategy = CullingManager.instance.GetCullingStrategy<AlwaysUpdateCullingStrategy>();
  81. m_CullingStrategy.AddRequestingObject(this);
  82. }
  83. void OnValidate()
  84. {
  85. m_Weight = Mathf.Clamp01(m_Weight);
  86. OnEditorDataValidate();
  87. }
  88. void Reset()
  89. {
  90. FindChildSolvers();
  91. OnEditorDataValidate();
  92. }
  93. void FindChildSolvers()
  94. {
  95. m_Solvers.Clear();
  96. var solvers = new List<Solver2D>();
  97. transform.GetComponentsInChildren<Solver2D>(true, solvers);
  98. foreach (var solver in solvers)
  99. {
  100. if (solver.GetComponentInParent<IKManager2D>() == this)
  101. AddSolver(solver);
  102. }
  103. }
  104. /// <summary>
  105. /// Add Solver to the manager.
  106. /// </summary>
  107. /// <param name="solver">Solver to add.</param>
  108. public void AddSolver(Solver2D solver)
  109. {
  110. if (!m_Solvers.Contains(solver))
  111. {
  112. m_Solvers.Add(solver);
  113. AddSolverEditorData();
  114. }
  115. }
  116. /// <summary>
  117. /// Remove Solver from the manager.
  118. /// </summary>
  119. /// <param name="solver">Solver to remove.</param>
  120. public void RemoveSolver(Solver2D solver)
  121. {
  122. RemoveSolverEditorData(solver);
  123. m_Solvers.Remove(solver);
  124. }
  125. /// <summary>
  126. /// Updates the Solvers in this manager.
  127. /// </summary>
  128. public void UpdateManager()
  129. {
  130. if(m_Solvers.Count == 0)
  131. return;
  132. var profilerMarker = new ProfilerMarker("IKManager2D.UpdateManager");
  133. profilerMarker.Begin();
  134. ToggleCulling(!m_AlwaysUpdate);
  135. var solverInitialized = false;
  136. for (var i = 0; i < m_Solvers.Count; i++)
  137. {
  138. var solver = m_Solvers[i];
  139. if (solver == null || !solver.isActiveAndEnabled)
  140. continue;
  141. if (!solver.isValid)
  142. {
  143. solver.Initialize();
  144. solverInitialized = true;
  145. }
  146. if(!m_CullingEnabled)
  147. solver.UpdateIK(m_Weight);
  148. }
  149. if (m_CullingEnabled)
  150. {
  151. if (solverInitialized || m_TransformIdCache == null)
  152. CacheSolversTransformIds();
  153. var canUpdate = m_AlwaysUpdate || m_CullingStrategy.AreBonesVisible(m_TransformIdCache);
  154. if (canUpdate)
  155. {
  156. for (var i = 0; i < m_Solvers.Count; i++)
  157. {
  158. var solver = m_Solvers[i];
  159. if (solver == null || !solver.isActiveAndEnabled)
  160. continue;
  161. solver.UpdateIK(weight);
  162. }
  163. }
  164. }
  165. profilerMarker.End();
  166. }
  167. void CacheSolversTransformIds()
  168. {
  169. var transformCache = new HashSet<int>();
  170. for (var s = 0; s < solvers.Count; s++)
  171. {
  172. var solver = solvers[s];
  173. for (var c = 0; c < solver.chainCount; c++)
  174. {
  175. var chain = solver.GetChain(c);
  176. for (var b = 0; b < chain.transformCount; b++)
  177. {
  178. var boneTransform = chain.transforms[b];
  179. if(boneTransform != null)
  180. transformCache.Add(boneTransform.GetInstanceID());
  181. }
  182. }
  183. }
  184. m_TransformIdCache = transformCache.ToArray();
  185. }
  186. /// <summary>
  187. /// Used by the animation clip preview window. Recommended to not use outside of this purpose.
  188. /// </summary>
  189. public void OnPreviewUpdate()
  190. {
  191. #if UNITY_EDITOR
  192. if (IsInGUIUpdateLoop())
  193. UpdateManager();
  194. #endif
  195. }
  196. static bool IsInGUIUpdateLoop() => Event.current != null;
  197. void LateUpdate()
  198. {
  199. UpdateManager();
  200. }
  201. #if UNITY_EDITOR
  202. internal static Events.UnityEvent onDrawGizmos = new Events.UnityEvent();
  203. void OnDrawGizmos()
  204. {
  205. onDrawGizmos.Invoke();
  206. }
  207. #endif
  208. }
  209. }