Honeycomb  0.1
Component-Model Framework
ComObject.h
Go to the documentation of this file.
1 // Honeycomb, Copyright (C) 2015 NewGamePlus Inc. Distributed under the Boost Software License v1.0.
2 #pragma once
3 
5 
6 namespace honey
7 {
8 
11 
13 
17 class ComObject : public Object
18 {
19  friend class Component;
20 
22  struct Slot
23  {
24  Slot() : type(nullptr) {}
26  typedef vector<Component::Ptr> List;
27  Map map;
28  List list;
29  const ComRegistry::Type* type;
30  };
31  typedef stdutil::unordered_map<Id, Slot, SmallAllocator> SlotMap;
32 
33 public:
34  SIGNAL_DECL(ComObject)
36  SIGNAL(sigComInsert, (ComObject& src, Component& com));
38  SIGNAL(sigComRemove, (ComObject& src, Component& com));
40  SIGNAL(sigSetInstId, (ComObject& src, Id id));
41 
43  virtual ~ComObject() { removeComs(); }
44 
46  virtual void setInstId(const Id& id)
47  {
48  listeners().dispatch<sigSetInstId>(*this, id);
50  }
51 
53 
59  void addCom(Component& com, bool createDeps = false) { insertCom_priv(com, -1, createDeps); }
60 
62  void addCom(Component* com, bool createDeps = false) { assert(com); addCom(*com, createDeps); }
63 
65 
69  void insertCom(Component& com, szt index, bool createDeps = false)
70  { insertCom_priv(com, index, createDeps); }
71 
73  template<class Com>
74  bool hasCom(const Id& id = idnull) const { return hasComInSlot(Com::s_comType(), id); }
75 
77  bool hasComInSlot(const Id& type, const Id& id = idnull) const
78  {
79  auto slot = this->slot(type);
80  if (!slot) return false;
81  if (id != idnull)
82  {
83  auto it = slot->map.find(id);
84  return it != slot->map.end();
85  }
86  return slot->list.size();
87  }
88 
90  template<class Com>
91  szt comCount() const { return comCountInSlot(Com::s_comType()); }
92 
94  szt comCountInSlot(const Id& type) const
95  {
96  auto slot = this->slot(type);
97  return slot ? slot->list.size() : 0;
98  }
99 
101  auto comSlots() const -> decltype(keys(declval<const SlotMap>()))
102  { return keys(_slotMap); }
103 
105  template<class Com>
106  Com& com() const
107  {
108  auto slot = this->slot(Com::s_comType());
109  assert(slot && slot->list.size(), sout() << "Component type not found: Request type: " << Com::s_comType());
110  return static_cast<Com&>(*slot->list[0]);
111  }
112 
114  template<class Com>
115  Com& com(const Id& id) const { return static_cast<Com&>(comInSlot(Com::s_comType(), id)); }
116 
118  Component& comInSlot(const Id& type, const Id& id = idnull) const
119  {
120  Component* com = nullptr;
121  auto slot = this->slot(type);
122  if (slot)
123  {
124  if (id != idnull)
125  {
126  auto it = slot->map.find(id);
127  com = it != slot->map.end() ? it->second : nullptr;
128  }
129  else
130  com = slot->list[0];
131  }
132  assert(com, sout() << "Component type not found: Request type: " << type << " ; Id : " << id);
133  return *com;
134  }
135 
137  template<class Com>
138  const vector<typename Com::Ptr>& coms() const { return reinterpret_cast<const vector<typename Com::Ptr>&>(comsInSlot(Com::s_comType())); }
139 
141  const vector<Component::Ptr>& comsInSlot(const Id& type) const
142  {
143  auto slot = this->slot(type);
144  return slot ? slot->list : _nullComs;
145  }
146 
148 
153  void removeCom(Component& com, bool removeDeps = false)
154  {
155  auto slotIt = _slotMap.find(com.comType());
156  if (slotIt == _slotMap.end()) return;
157  auto& slot = slotIt->second;
158  auto it = std::find(slot.list.begin(), slot.list.end(), &com);
159  if (it != slot.list.end()) removeComInSlot(slotIt, it, removeDeps);
160  }
161 
163  template<class Com>
164  void removeCom(const Id& id = idnull, bool removeDeps = false)
165  {
166  if (!hasCom<Com>(id)) return;
167  removeCom(com<Com>(id), removeDeps);
168  }
169 
171  template<class Com>
172  void removeComAtIndex(szt index, bool removeDeps = false) { removeComInSlot(Com::s_comType(), index, removeDeps); }
173 
175  void removeComInSlot(const Id& type, szt index, bool removeDeps = false)
176  {
177  auto slotIt = _slotMap.find(type);
178  assert(slotIt != _slotMap.end() && index < slotIt->second.list.size());
179  removeComInSlot(slotIt, slotIt->second.list.begin() + index, removeDeps);
180  }
181 
183  template<class Com>
184  void removeComs(bool removeDeps = false) { removeComsInSlot(Com::s_comType(), removeDeps); }
186  void removeComs();
188  void removeComsInSlot(const Id& type, bool removeDeps = false)
189  {
190  auto slotIt = _slotMap.find(type);
191  if (slotIt == _slotMap.end()) return;
192  removeComsInSlot(slotIt, removeDeps);
193  }
194 
196  ListenerList& listeners() { return _listeners; }
197 
198 private:
200  struct slotDepOrderCmp { bool operator() (const ComRegistry::Type* type, const ComRegistry::Type* type2) const { return type->depOrder() < type2->depOrder(); } };
201  typedef multiset<const ComRegistry::Type*, slotDepOrderCmp, SmallAllocator<const ComRegistry::Type*>> SlotDepOrder;
202 
204  const Slot* slot(const Id& type) const { auto it = _slotMap.find(type); return it != _slotMap.end() ? &it->second : nullptr; }
205  Slot* slot(const Id& type) { auto it = _slotMap.find(type); return it != _slotMap.end() ? &it->second : nullptr; }
206 
208  void insertCom_priv(Component& com, sdt index, bool createDeps);
210  void removeComInSlot(SlotMap::iterator slotIt, Slot::List::iterator it, bool removeDeps);
211  void removeComsInSlot(SlotMap::iterator slotIt, bool removeDeps);
212 
214  void updateComMap(Component& com, const Id& id);
215 
216  SlotMap _slotMap;
217  SlotDepOrder _slotDepOrder;
218  ListenerList _listeners;
219 
220  static const vector<Component::Ptr> _nullComs;
221 };
222 
224 
225 }
void addCom(Component &com, bool createDeps=false)
Add a component reference. The component is added to the end of its slot (and any supertype slots)...
Definition: ComObject.h:59
Component & comInSlot(const Id &type, const Id &id=idnull) const
Get a single component of type with id. If id is null then first component in slot will be returned...
Definition: ComObject.h:118
virtual const ComRegistry::Type & comType() const =0
Get type of component.
ListenerList & listeners()
Get listener list.
Definition: ComObject.h:196
void removeComs()
Remove all components. Components are removed in type-dependent order.
Definition: ComObject.cpp:159
void addCom(Component *com, bool createDeps=false)
Wrapper for pointer arg.
Definition: ComObject.h:62
ptrdiff_t sdt
Size difference type, shorthand for ptrdiff_t.
Definition: Core.h:92
virtual void setInstId(const Id &id)
Set per instance id.
Definition: Object.h:19
Iter find(Range &&, Seqs &&..., Func &&pred)
Find an element in a series of sequences.
std::unordered_map< Key, Value, std::hash< Key >, std::equal_to< Key >, Alloc< pair< const Key, Value >>> unordered_map
std::unordered_map with custom allocator
Definition: StdUtil.h:83
void removeComs(bool removeDeps=false)
removeComsInSlot() with type Com
Definition: ComObject.h:184
void removeCom(const Id &id=idnull, bool removeDeps=false)
Remove a single component of type Com with id. O(n) complexity unless id is null. If id is null then ...
Definition: ComObject.h:164
void dispatch(Args &&...args) const
Send a signal to all listeners.
Definition: ListenerList.h:52
void removeCom(Component &com, bool removeDeps=false)
Remove a single component. O(n) complexity.
Definition: ComObject.h:153
auto keys(Range &&range) -> Range_< TupleIter< mt_iterOf(range), 0 >, TupleIter< mt_iterOf(range), 0 >>
Create a range over the keys of a map or map iterator range.
Definition: StdUtil.h:23
const vector< Component::Ptr > & comsInSlot(const Id &type) const
Get all components of type. May return empty list. O(1) complexity.
Definition: ComObject.h:141
szt comCount() const
comCountInSlot() with type Com
Definition: ComObject.h:91
ostringstream sout()
Shorthand to create ostringstream.
Definition: Stream.h:15
#define assert(...)
Forwards to assert_#args. See assert_1(), assert_2().
Definition: Debug.h:24
bool hasCom(const Id &id=idnull) const
hasComInSlot() with type Com
Definition: ComObject.h:74
#define idnull
Null id.
Definition: Id.h:124
SIGNAL(sigComInsert,(ComObject &src, Component &com))
Called after component is inserted.
virtual void setInstId(const Id &id)
Override from object, sends message about change.
Definition: ComObject.h:46
szt comCountInSlot(const Id &type) const
Get number of components of type that this object contains. O(1) complexity.
Definition: ComObject.h:94
void insertCom(Component &com, szt index, bool createDeps=false)
Add a component reference. The component is inserted into its slot at index.
Definition: ComObject.h:69
const vector< typename Com::Ptr > & coms() const
comsInSlot() with type Com
Definition: ComObject.h:138
bool hasComInSlot(const Id &type, const Id &id=idnull) const
Check if object contains any components of type (with id).
Definition: ComObject.h:77
size_t szt
Size type, shorthand for size_t.
Definition: Core.h:90
#define SIGNAL_DECL(BaseClass)
Call once inside a class that has signals.
Definition: Signal.h:18
friend class Component
Definition: ComObject.h:19
Base class for components. Components can only be attached to one ComObject at a time.
Definition: Component.h:172
Component object. Object that consists of a collection of components.
Definition: ComObject.h:17
void removeComInSlot(const Id &type, szt index, bool removeDeps=false)
Remove component of type at index. O(1) complexity, must exist.
Definition: ComObject.h:175
Holds a name string and its hashed value for fast comparison ops. See String Identifier.
Definition: Id.h:25
auto comSlots() const -> decltype(keys(declval< const SlotMap >()))
Get iterator over all slots in this object. A slot may contain one or many components.
Definition: ComObject.h:101
Base class for objects.
Definition: Object.h:12
Collection of listeners.
Definition: ListenerList.h:16
Global Honeycomb namespace.
void removeComAtIndex(szt index, bool removeDeps=false)
removeComInSlot() with type Com
Definition: ComObject.h:172
Com & com(const Id &id) const
comInSlot() with type Com
Definition: ComObject.h:115
Component type.
Definition: Component.h:87
int depOrder() const
Get dependency order. A component type can depend only on those with a lower order.
Definition: Component.h:104
void removeComsInSlot(const Id &type, bool removeDeps=false)
Remove all components of type. Components are removed from slot list in reverse order.
Definition: ComObject.h:188
Com & com() const
Get component of type Com. Returns first component in slot, must exist.
Definition: ComObject.h:106
OutSeq && map(Range &&, Seqs &&..., OutSeq &&, Func &&)
Transform a series of sequences into an output.