All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
MortonKeyEventProxy.h
1 #pragma once
2 
3 #include "ICallback.h"
4 #include "IMortonKeyBasedEventProvider.h"
5 
6 #include <array>
7 #include <memory>
8 
9 namespace Eegeo
10 {
11  namespace Helpers
12  {
13  template <typename TEvent, int MortonKeyDepth>
14  class MortonKeyEventProxy : public ICallback1<const Streaming::MortonKey>, public IMortonKeyBasedEventProvider<TEvent>
15  {
16  public:
17  using EventType = TEvent;
18  static constexpr int Depth = MortonKeyDepth;
19 
20  virtual TEvent& GetEventForMortonKey(Streaming::MortonKey mortonKey) override
21  {
22  return m_quadTree[mortonKey];
23  }
24 
25  virtual void operator()(const Streaming::MortonKey& mortonKey) const override
26  {
27  m_quadTree(mortonKey);
28  }
29 
30  virtual int GetPreferredDepth() const override
31  {
32  return MortonKeyDepth;
33  }
34 
35  private:
36  // For now, there's no TEvent2, so we don't need to deal with picking the right class.
37  // Really, events should be variadic templates with perfect forwarding.
38  struct QuadTreeNode : public TEvent1<TEvent>
39  {
40  QuadTreeNode(QuadTreeNode* parent)
41  : TEvent1<TEvent>()
42  , parent(parent)
43  {}
44  QuadTreeNode() = delete;
45 
46  virtual void RemoveChild(int quadrant) = 0;
47 
48  QuadTreeNode* parent;
49  };
50 
51  struct QuadTreeRegularNode : public QuadTreeNode
52  {
53  QuadTreeRegularNode(Streaming::MortonKey nodeKey, QuadTreeNode* parent)
54  : QuadTreeNode(parent)
55  , nodeKey(nodeKey)
56  , children({nullptr, nullptr, nullptr, nullptr})
57  {}
58  QuadTreeRegularNode() = delete;
59 
60  Streaming::MortonKey nodeKey;
61  std::array<std::unique_ptr<QuadTreeRegularNode>, 4> children;
62 
63  void Cleanup()
64  {
65  if (this->m_callbacks.empty())
66  {
67  for (const auto& child : children)
68  {
69  if (child)
70  {
71  return;
72  }
73  }
74  this->parent->RemoveChild(nodeKey.Element(nodeKey.Depth() - 1));
75  }
76  }
77 
78  void Unregister(typename TEvent1<TEvent>::CallbackType& callback) override
79  {
80  TEvent1<TEvent>::Unregister(callback);
81  Cleanup();
82  }
83 
84  void RemoveChild(int quadrant) override
85  {
86  children[quadrant] = nullptr;
87  Cleanup();
88  }
89 
90  TEvent& operator[] (const Streaming::MortonKey& mortonKey)
91  {
92  if (nodeKey == mortonKey || nodeKey.Depth() == Depth)
93  {
94  return *this;
95  }
96  else
97  {
98  int childIndex = mortonKey.Element(nodeKey.Depth());
99  auto& child = children[childIndex];
100  if (!child)
101  {
102  // eww, no std::make_unique
103  child.reset(Eegeo_NEW(QuadTreeRegularNode)(nodeKey.Push(childIndex), this));
104  }
105  return (*child)[mortonKey];
106  }
107  }
108 
109  void operator()(const Streaming::MortonKey& mortonKey) const
110  {
111  this->Raise(mortonKey);
112  if (mortonKey.Depth() > nodeKey.Depth())
113  {
114  const auto& child = children[mortonKey.Element(nodeKey.Depth())];
115  if (child)
116  {
117  (*child)(mortonKey);
118  }
119  }
120  else
121  {
122  for (const auto& child : children)
123  {
124  if (child)
125  {
126  (*child)(mortonKey);
127  }
128  }
129  }
130  }
131  };
132 
133  struct QuadTreeRootNode : public QuadTreeNode
134  {
135  QuadTreeRootNode()
136  : QuadTreeNode(nullptr)
137  , children({nullptr, nullptr, nullptr, nullptr, nullptr, nullptr})
138  {}
139  std::array<std::unique_ptr<QuadTreeRegularNode>, 6> children;
140 
141  void RemoveChild(int face) override
142  {
143  children[face] = nullptr;
144  }
145 
146  TEvent& operator[] (const Streaming::MortonKey& mortonKey)
147  {
148  if (Depth == 0)
149  {
150  return *this;
151  }
152  else
153  {
154  auto& child = children[mortonKey.Face()];
155  if (!child)
156  {
157  // eww, no std::make_unique
158  child.reset(Eegeo_NEW(QuadTreeRegularNode)(Streaming::MortonKey(mortonKey.Face()), this));
159  }
160  return (*child)[mortonKey];
161  }
162  }
163 
164  void operator()(const Streaming::MortonKey& mortonKey) const
165  {
166  this->Raise(mortonKey);
167  auto& child = children[mortonKey.Face()];
168  if (child)
169  {
170  (*child)(mortonKey);
171  }
172  }
173  };
174 
175  QuadTreeRootNode m_quadTree;
176  };
177  }
178 }