PageRenderTime 61ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/Framework/Nine/SceneQuery.cs

http://nine.codeplex.com
C# | 126 lines | 100 code | 21 blank | 5 comment | 19 complexity | 0443292a983ef593fcaf775003c0fab0 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, Apache-2.0
  1. namespace Nine
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using Microsoft.Xna.Framework;
  6. /// <summary>
  7. /// Traverses the scene hierarchy and find all the objects that implements T.
  8. /// </summary>
  9. class SceneQuery<T> : ISpatialQuery<T> where T : class
  10. {
  11. CollectionAdapter adapter;
  12. List<ISceneManager<ISpatialQueryable>> sceneManagers;
  13. IList<object> topLevelObjects;
  14. public SceneQuery(List<ISceneManager<ISpatialQueryable>> sceneManagers, IList<object> topLevelObjects, Predicate<T> condition)
  15. {
  16. this.sceneManagers = sceneManagers;
  17. this.topLevelObjects = topLevelObjects;
  18. this.adapter = new CollectionAdapter(condition);
  19. }
  20. public void FindAll(ref BoundingSphere boundingSphere, ICollection<T> result)
  21. {
  22. adapter.Result = result;
  23. adapter.IncludeTopLevelNonSpatialQueryableDesendants(topLevelObjects);
  24. var count = sceneManagers.Count;
  25. for (int i = 0; i < count; ++i)
  26. sceneManagers[i].FindAll(ref boundingSphere, adapter);
  27. adapter.Result = null;
  28. }
  29. public void FindAll(ref Ray ray, ICollection<T> result)
  30. {
  31. adapter.Result = result;
  32. adapter.IncludeTopLevelNonSpatialQueryableDesendants(topLevelObjects);
  33. var count = sceneManagers.Count;
  34. for (int i = 0; i < count; ++i)
  35. sceneManagers[i].FindAll(ref ray, adapter);
  36. adapter.Result = null;
  37. }
  38. public void FindAll(ref BoundingBox boundingBox, ICollection<T> result)
  39. {
  40. adapter.Result = result;
  41. adapter.IncludeTopLevelNonSpatialQueryableDesendants(topLevelObjects);
  42. var count = sceneManagers.Count;
  43. for (int i = 0; i < count; ++i)
  44. sceneManagers[i].FindAll(ref boundingBox, adapter);
  45. adapter.Result = null;
  46. }
  47. public void FindAll(BoundingFrustum boundingFrustum, ICollection<T> result)
  48. {
  49. adapter.Result = result;
  50. adapter.IncludeTopLevelNonSpatialQueryableDesendants(topLevelObjects);
  51. var count = sceneManagers.Count;
  52. for (int i = 0; i < count; ++i)
  53. sceneManagers[i].FindAll(boundingFrustum, adapter);
  54. adapter.Result = null;
  55. }
  56. class CollectionAdapter : SpatialQueryCollectionAdapter<ISpatialQueryable>
  57. {
  58. public ICollection<T> Result;
  59. private ISpatialQueryable currentItem;
  60. private Func<object, TraverseOptions> traverser;
  61. private Predicate<T> condition;
  62. public CollectionAdapter(Predicate<T> condition)
  63. {
  64. this.condition = condition;
  65. this.traverser = new Func<object, TraverseOptions>(FindNonSpatialQueryableDescendantTraverser);
  66. }
  67. public override void Add(ISpatialQueryable item)
  68. {
  69. currentItem = item;
  70. ContainerTraverser.Traverse(item, traverser);
  71. currentItem = null;
  72. }
  73. public void IncludeTopLevelNonSpatialQueryableDesendants(IList<object> topLevelObjects)
  74. {
  75. var count = topLevelObjects.Count;
  76. for (int i = 0; i < count; ++i)
  77. {
  78. ContainerTraverser.Traverse(topLevelObjects[i], traverser);
  79. }
  80. }
  81. private TraverseOptions FindNonSpatialQueryableDescendantTraverser(object item)
  82. {
  83. T t;
  84. // Skip ISpatialQueryables since they are explicitly added to the scene manager,
  85. // but only if it doesn't equal to the current T.
  86. var queryable = item as ISpatialQueryable;
  87. if (queryable != null)
  88. {
  89. if (queryable == currentItem)
  90. {
  91. t = queryable as T;
  92. if (t != null && (condition == null || condition(t)))
  93. Result.Add(t);
  94. return TraverseOptions.Continue;
  95. }
  96. return TraverseOptions.Skip;
  97. }
  98. t = item as T;
  99. if (t != null && (condition == null || condition(t)))
  100. Result.Add(t);
  101. return TraverseOptions.Continue;
  102. }
  103. }
  104. }
  105. }