125 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using UnityEngine;
 | |
| using UnityEngine.Timeline;
 | |
| 
 | |
| namespace UnityEditor.Timeline
 | |
| {
 | |
|     interface IBounds
 | |
|     {
 | |
|         Rect boundingRect { get; }
 | |
|     }
 | |
| 
 | |
|     class SpacePartitioner
 | |
|     {
 | |
|         internal class CachedList<T>
 | |
|         {
 | |
|             public static readonly List<T> Instance = new List<T>(1000);
 | |
|         }
 | |
| 
 | |
|         struct Entry : IInterval
 | |
|         {
 | |
|             public object item { get; set; }
 | |
|             public long intervalStart { get; set; }
 | |
|             public long intervalEnd { get; set; }
 | |
|             public Rect bounds { get; set; }
 | |
| 
 | |
|             private const float kPrecision = 100.0f;
 | |
|             private const float kMaxFloat = (float)long.MaxValue;
 | |
|             private const float kMinFloat = (float)long.MinValue;
 | |
| 
 | |
|             static public Int64 FromFloat(float f)
 | |
|             {
 | |
|                 if (Single.IsPositiveInfinity(f))
 | |
|                     return long.MaxValue;
 | |
|                 if (Single.IsNegativeInfinity(f))
 | |
|                     return long.MinValue;
 | |
| 
 | |
|                 f = Mathf.Clamp(f, kMinFloat, kMaxFloat);              // prevent overflow of floats
 | |
|                 f = Mathf.Clamp(f * kPrecision, kMinFloat, kMaxFloat); // clamp to 'long' range
 | |
|                 return (long)(f);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         const EventType k_GuiEventLock = EventType.Repaint;
 | |
| 
 | |
|         IntervalTree<Entry> m_Tree = new IntervalTree<Entry>();
 | |
|         List<Entry> m_CacheList = new List<Entry>();
 | |
| 
 | |
|         public void Clear()
 | |
|         {
 | |
|             m_Tree.Clear();
 | |
|         }
 | |
| 
 | |
|         public void AddBounds(IBounds bounds)
 | |
|         {
 | |
|             AddBounds(bounds, bounds.boundingRect);
 | |
|         }
 | |
| 
 | |
|         public void AddBounds(object item, Rect rect)
 | |
|         {
 | |
|             if (item == null)
 | |
|                 throw new ArgumentNullException("item");
 | |
| 
 | |
|             m_Tree.Add(new Entry()
 | |
|             {
 | |
|                 intervalStart = Entry.FromFloat(rect.yMin),
 | |
|                 intervalEnd = Entry.FromFloat(rect.yMax),
 | |
|                 bounds = rect,
 | |
|                 item = item
 | |
|             }
 | |
|             );
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Get items of type T at a given position
 | |
|         /// </summary>
 | |
|         /// <param name="position"></param>
 | |
|         /// <param name="inClipSpace"></param>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <remarks>
 | |
|         /// Uses a (1,1) sized box
 | |
|         /// Use .ToList() or .ToArray() when not enumerating the result immediately
 | |
|         /// </remarks>
 | |
|         /// <returns></returns>
 | |
|         public IEnumerable<T> GetItemsAtPosition<T>(Vector2 position)
 | |
|         {
 | |
|             return GetItemsInArea<T>(new Rect(position.x, position.y, 1, 1));
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         ///
 | |
|         /// </summary>
 | |
|         /// <param name="area"></param>
 | |
|         /// <param name="inClipSpace"></param>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <returns></returns>
 | |
|         public IEnumerable<T> GetItemsInArea<T>(Rect area)
 | |
|         {
 | |
|             m_CacheList.Clear();
 | |
|             m_Tree.IntersectsWithRange(long.MinValue, long.MaxValue, m_CacheList);
 | |
| 
 | |
|             var list = CachedList<T>.Instance;
 | |
|             list.Clear();
 | |
|             foreach (var i in m_CacheList)
 | |
|             {
 | |
|                 if (i.item is T && i.bounds.Overlaps(area))
 | |
|                     list.Add((T)i.item);
 | |
|             }
 | |
|             return list;
 | |
|         }
 | |
| 
 | |
|         public void DebugDraw(Color fillColor, Color outlineColor)
 | |
|         {
 | |
|             m_CacheList.Clear();
 | |
|             m_Tree.IntersectsWithRange(long.MinValue, long.MaxValue, m_CacheList);
 | |
|             HandleUtility.ApplyWireMaterial();
 | |
| 
 | |
|             foreach (var item in m_CacheList)
 | |
|             {
 | |
|                 Handles.DrawSolidRectangleWithOutline(item.bounds, fillColor, outlineColor);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |