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.

SpriteSkinVisibilityCullingStrategy.cs 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine.U2D.Animation;
  4. namespace UnityEngine.U2D.IK
  5. {
  6. internal class SpriteSkinVisibilityCullingStrategy : BaseCullingStrategy
  7. {
  8. /// <summary>
  9. /// SpriteSkin registry used to keep visibility state of a SpriteSkin and bone transforms.
  10. /// </summary>
  11. class SpriteSkinRegistry
  12. {
  13. public int[] boneIds;
  14. public bool isVisible;
  15. public SpriteSkinRegistry(int[] boneIds, bool isSkinVisible)
  16. {
  17. this.boneIds = boneIds;
  18. isVisible = isSkinVisible;
  19. }
  20. }
  21. /// <summary>
  22. /// Maps SpriteSkins to SpriteSkinRegistry.
  23. /// </summary>
  24. Dictionary<SpriteSkin, SpriteSkinRegistry> m_SpriteSkinRegistries;
  25. /// <summary>
  26. /// Counts (value) how many visible Sprite Skins use a given bone (key).
  27. /// </summary>
  28. Dictionary<int, int> m_BoneVisibilityCount;
  29. public override bool AreBonesVisible(IList<int> boneTransformIds)
  30. {
  31. for (var i = 0; i < boneTransformIds.Count; i++)
  32. {
  33. var boneId = boneTransformIds[i];
  34. if (m_BoneVisibilityCount.ContainsKey(boneId))
  35. return m_BoneVisibilityCount[boneId] > 0;
  36. }
  37. return false;
  38. }
  39. protected override void OnInitialize()
  40. {
  41. m_SpriteSkinRegistries = new Dictionary<SpriteSkin, SpriteSkinRegistry>();
  42. m_BoneVisibilityCount = new Dictionary<int, int>();
  43. var spriteSkins = SpriteSkinContainer.instance.spriteSkins;
  44. for (var i = 0; i < spriteSkins.Count; i++)
  45. UpdateSpriteSkinVisibility(spriteSkins[i]);
  46. AddListeners();
  47. }
  48. protected override void OnDisable()
  49. {
  50. m_SpriteSkinRegistries.Clear();
  51. m_BoneVisibilityCount.Clear();
  52. RemoveListeners();
  53. }
  54. void AddListeners()
  55. {
  56. SpriteSkinContainer.onAddedSpriteSkin += UpdateSpriteSkinVisibility;
  57. SpriteSkinContainer.onRemovedSpriteSkin += UnregisterSpriteSkin;
  58. SpriteSkinContainer.onBoneTransformChanged += OnBoneTransformChanged;
  59. }
  60. void RemoveListeners()
  61. {
  62. SpriteSkinContainer.onAddedSpriteSkin -= UpdateSpriteSkinVisibility;
  63. SpriteSkinContainer.onRemovedSpriteSkin -= UnregisterSpriteSkin;
  64. SpriteSkinContainer.onBoneTransformChanged -= OnBoneTransformChanged;
  65. }
  66. protected override void OnUpdate()
  67. {
  68. foreach (var (spriteSkin, registry) in m_SpriteSkinRegistries)
  69. {
  70. var isVisible = spriteSkin.spriteRenderer.isVisible;
  71. if (registry.isVisible != isVisible)
  72. {
  73. registry.isVisible = isVisible;
  74. RecalculateVisibility(registry);
  75. }
  76. }
  77. }
  78. void OnBoneTransformChanged(SpriteSkin spriteSkin)
  79. {
  80. UnregisterSpriteSkinBonesMapping(spriteSkin);
  81. RegisterSpriteSkinBonesMapping(spriteSkin);
  82. UpdateSpriteSkinVisibility(spriteSkin);
  83. }
  84. bool IsSpriteSkinRegistered(SpriteSkin spriteSkin) => m_SpriteSkinRegistries.ContainsKey(spriteSkin);
  85. void UnregisterSpriteSkin(SpriteSkin spriteSkin)
  86. {
  87. UnregisterSpriteSkinBonesMapping(spriteSkin);
  88. }
  89. void UpdateSpriteSkinVisibility(SpriteSkin spriteSkin)
  90. {
  91. var visible = spriteSkin.spriteRenderer.isVisible;
  92. var registry = RegisterSpriteSkinBonesMapping(spriteSkin);
  93. if (registry.isVisible == visible)
  94. return;
  95. registry.isVisible = visible;
  96. RecalculateVisibility(registry);
  97. }
  98. SpriteSkinRegistry RegisterSpriteSkinBonesMapping(SpriteSkin spriteSkin)
  99. {
  100. if (IsSpriteSkinRegistered(spriteSkin))
  101. return m_SpriteSkinRegistries[spriteSkin];
  102. var bones = spriteSkin.boneTransforms ?? Array.Empty<Transform>();
  103. var records = new int[bones.Length];
  104. var newRegistry = new SpriteSkinRegistry(records, false);
  105. for (var i = 0; i < bones.Length; i++)
  106. {
  107. var bone = bones[i];
  108. if (bone == null)
  109. continue;
  110. var id = bone.GetInstanceID();
  111. records[i] = id;
  112. }
  113. m_SpriteSkinRegistries[spriteSkin] = newRegistry;
  114. return newRegistry;
  115. }
  116. void UnregisterSpriteSkinBonesMapping(SpriteSkin spriteSkin)
  117. {
  118. if (!IsSpriteSkinRegistered(spriteSkin))
  119. return;
  120. var registry = m_SpriteSkinRegistries[spriteSkin];
  121. registry.isVisible = false;
  122. m_SpriteSkinRegistries.Remove(spriteSkin);
  123. RecalculateVisibility(registry);
  124. }
  125. void RecalculateVisibility(SpriteSkinRegistry registry)
  126. {
  127. var bones = registry.boneIds;
  128. var visible = registry.isVisible;
  129. var countOperation = visible ? 1 : -1;
  130. for (var i = 0; i < bones.Length; i++)
  131. {
  132. var bone = bones[i];
  133. if (m_BoneVisibilityCount.ContainsKey(bone))
  134. {
  135. var count = m_BoneVisibilityCount[bone] + countOperation;
  136. if (count <= 0)
  137. m_BoneVisibilityCount.Remove(bone);
  138. else
  139. m_BoneVisibilityCount[bone] = count;
  140. }
  141. else if (visible)
  142. m_BoneVisibilityCount[bone] = 1;
  143. }
  144. }
  145. }
  146. }