SpacePartitioner.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.Timeline;
  5. namespace UnityEditor.Timeline
  6. {
  7. interface IBounds
  8. {
  9. Rect boundingRect { get; }
  10. }
  11. class SpacePartitioner
  12. {
  13. internal class CachedList<T>
  14. {
  15. public static readonly List<T> Instance = new List<T>(1000);
  16. }
  17. struct Entry : IInterval
  18. {
  19. public object item { get; set; }
  20. public long intervalStart { get; set; }
  21. public long intervalEnd { get; set; }
  22. public Rect bounds { get; set; }
  23. private const float kPrecision = 100.0f;
  24. private const float kMaxFloat = (float)long.MaxValue;
  25. private const float kMinFloat = (float)long.MinValue;
  26. static public Int64 FromFloat(float f)
  27. {
  28. if (Single.IsPositiveInfinity(f))
  29. return long.MaxValue;
  30. if (Single.IsNegativeInfinity(f))
  31. return long.MinValue;
  32. f = Mathf.Clamp(f, kMinFloat, kMaxFloat); // prevent overflow of floats
  33. f = Mathf.Clamp(f * kPrecision, kMinFloat, kMaxFloat); // clamp to 'long' range
  34. return (long)(f);
  35. }
  36. }
  37. const EventType k_GuiEventLock = EventType.Repaint;
  38. IntervalTree<Entry> m_Tree = new IntervalTree<Entry>();
  39. List<Entry> m_CacheList = new List<Entry>();
  40. public void Clear()
  41. {
  42. m_Tree.Clear();
  43. }
  44. public void AddBounds(IBounds bounds)
  45. {
  46. AddBounds(bounds, bounds.boundingRect);
  47. }
  48. public void AddBounds(object item, Rect rect)
  49. {
  50. if (item == null)
  51. throw new ArgumentNullException("item");
  52. m_Tree.Add(new Entry()
  53. {
  54. intervalStart = Entry.FromFloat(rect.yMin),
  55. intervalEnd = Entry.FromFloat(rect.yMax),
  56. bounds = rect,
  57. item = item
  58. }
  59. );
  60. }
  61. /// <summary>
  62. /// Get items of type T at a given position
  63. /// </summary>
  64. /// <param name="position"></param>
  65. /// <param name="inClipSpace"></param>
  66. /// <typeparam name="T"></typeparam>
  67. /// <remarks>
  68. /// Uses a (1,1) sized box
  69. /// Use .ToList() or .ToArray() when not enumerating the result immediately
  70. /// </remarks>
  71. /// <returns></returns>
  72. public IEnumerable<T> GetItemsAtPosition<T>(Vector2 position)
  73. {
  74. return GetItemsInArea<T>(new Rect(position.x, position.y, 1, 1));
  75. }
  76. /// <summary>
  77. ///
  78. /// </summary>
  79. /// <param name="area"></param>
  80. /// <param name="inClipSpace"></param>
  81. /// <typeparam name="T"></typeparam>
  82. /// <returns></returns>
  83. public IEnumerable<T> GetItemsInArea<T>(Rect area)
  84. {
  85. m_CacheList.Clear();
  86. m_Tree.IntersectsWithRange(long.MinValue, long.MaxValue, m_CacheList);
  87. var list = CachedList<T>.Instance;
  88. list.Clear();
  89. foreach (var i in m_CacheList)
  90. {
  91. if (i.item is T && i.bounds.Overlaps(area))
  92. list.Add((T)i.item);
  93. }
  94. return list;
  95. }
  96. public void DebugDraw()
  97. {
  98. var kFillColor = new Color(1.0f, 1.0f, 1.0f, 0.1f);
  99. var kOutlineColor = Color.yellow;
  100. m_CacheList.Clear();
  101. m_Tree.IntersectsWithRange(long.MinValue, long.MaxValue, m_CacheList);
  102. HandleUtility.ApplyWireMaterial();
  103. foreach (var item in m_CacheList)
  104. {
  105. Handles.DrawSolidRectangleWithOutline(item.bounds, kFillColor, kOutlineColor);
  106. }
  107. }
  108. }
  109. }