Honeycomb  0.1
Component-Model Framework
Component.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 
4 #include "Honey/Object/Object.h"
6 #include "Honey/Graph/Tree.h"
7 #include "Honey/Graph/Dep.h"
8 
9 namespace honey
10 {
11 
13 
16 
19 #define COMPONENT(...) EVAL(TOKCAT(COMPONENT_, NUMARGS(__VA_ARGS__))(__VA_ARGS__))
20 
24 #define COMPONENT_1(Class) COMPONENT_2(Class, #Class)
25 #define COMPONENT_2(Class, typeId) COMPONENT_SUB(, Class, typeId)
27 
29 #define COMPONENT_SUB(...) EVAL(TOKCAT(COMPONENT_SUB_, NUMARGS(__VA_ARGS__))(__VA_ARGS__))
30 #define COMPONENT_SUB_2(SuperCom, Class) COMPONENT_SUB_3(SuperCom, Class, #Class)
32 #define COMPONENT_SUB_3(SuperCom, Class, typeId) \
34  friend class ComRegistry; \
35  \
36  typedef SharedPtr<Class> Ptr; \
37  typedef SharedPtr<const Class> ConstPtr; \
38  \
39  \
40  static ComRegistry::Type& s_comType() \
41  { \
42  mt_unused(__comReg_t); /* reference register var so it can't be compiled out */ \
43  static ComRegistry::Type obj( \
44  ComRegistry::Type( typeId, mt::identity<Class>() \
45  IFEMPTY(, COMMA mt::identity<SuperCom>(), SuperCom))); \
46  return obj; \
47  } \
48  \
49  \
50  virtual const ComRegistry::Type& comType() const { return s_comType(); } \
51  \
52  \
53  static mt::Void __comReg() \
54  { \
55  static bool init = false; if (init) return mt::Void(); init = true; \
56  ComRegistry::inst().reg<Class>(); \
57  return mt::Void(); \
58  } \
59  static mt::Void __comReg_t; /* for templated component reg */ \
60 
61 
63 #define COMPONENT_REG(Class) static mt::Void TOKCAT(__comReg_,__COUNTER__)(UNBRACKET(Class)::__comReg());
64 #define COMPONENT_REG_T(Template, Class) UNBRACKET(Template) mt::Void UNBRACKET(Class)::__comReg_t(__comReg());
66 
67 class Component;
68 
70 namespace component
71 {
73  template<class Com>
74  typename std::enable_if<std::is_default_constructible<Com>::value && !std::is_abstract<Com>::value, Component&>::type
75  create() { return *new Com; }
76  template<class Com>
77  typename mt::disable_if<std::is_default_constructible<Com>::value && !std::is_abstract<Com>::value, Component&>::type
78  create() { error_("ComRegistry can't create non-default-constructible components. Must specialize component::create()."); return *static_cast<Component*>(nullptr); }
79 }
80 
83 {
84  friend class ComObject;
85 public:
87  class Type : public NameId
88  {
89  friend class ComRegistry;
90  public:
91  template<class Com>
93  NameId(name),
94  _node(this), _create(&component::create<Com>),
95  _depNode(this, *this), _depCreate(&Com::createTypeDep), _depOrder(-1) {}
96 
97  template<class Com, class SuperCom>
99  Type(name, com) { _node.setParent(&SuperCom::s_comType()._node); }
100 
102  const vector<Type*>& hierarchy() const { return _hierarchy; }
104  int depOrder() const { return _depOrder; }
105 
107  bool isSubtypeOf(const Id& base) const
108  {
109  //For an early out, start at deepest subtype
110  auto range = reversed(_hierarchy);
111  return find(range, [&](auto& e) { return *e == base; }) != range.end();
112  }
113 
114  private:
115  typedef DepNode<Type*> DepNode;
116 
117  TreeNode<Type*> _node;
118  vector<Type*> _hierarchy;
119  function<Component& ()> _create;
120  DepNode _depNode;
121  function<DepNode ()> _depCreate;
122  int _depOrder;
123  };
125  typedef Type::DepNode DepNode;
127 
129  static mt_global(ComRegistry, inst,);
130 
132  template<class Com>
133  void reg()
134  {
135  Type& type = Com::s_comType();
136  if (_types.find(type) != _types.end()) return; //Already registered
137  _types[type] = &type;
138  //build hierarchy
139  for (auto* parent = &type._node; parent; parent = parent->getParent())
140  type._hierarchy.insert(type._hierarchy.begin(), **parent);
141  }
142 
144  Component& create(const Id& type) const
145  {
146  auto it = _types.find(type);
147  assert(it != _types.end(), sout() << "Component type not registered: " << type);
148  return it->second->_create();
149  }
150 
152  Type& type(const Id& id) const
153  {
154  auto it = _types.find(id);
155  assert(it != _types.end(), sout() << "Component type not registered: " << id);
156  return *it->second;
157  }
158 
160  const DepGraph& depGraph() const { return _depGraph; }
161 
162 private:
163  mt::Void buildDepGraph();
164 
165  unordered_map<Id, Type*> _types;
166  DepGraph _depGraph;
167 };
168 
169 class ComObject;
170 
172 class Component : public Object
173 {
174  friend class ComRegistry;
175  friend class ComObject;
176 public:
179 
180  Component() : _comObj(nullptr) {}
181  virtual ~Component() {}
182 
184  virtual const ComRegistry::Type& comType() const = 0;
185 
187  virtual void setInstId(const Id& id);
188 
190  ComObject& obj() const { assert(hasObj()); return *_comObj; }
192  bool hasObj() const { return _comObj; }
193 
195  ListenerList& listeners() { return _listeners; }
196 
197 protected:
200 
202  virtual void onComInsert() {}
204  virtual void onComRemove() {}
205 
206 private:
207  ComObject* _comObj;
208  ListenerList _listeners;
209 };
210 
212 
213 }
bool hasObj() const
Check if component is attached to a ComObject.
Definition: Component.h:192
ComObject & obj() const
Get ComObject that this component belongs to.
Definition: Component.h:190
Type::DepNode DepNode
Component type dep node. Type name is used as key.
Definition: Component.h:125
Type(const String &name, mt::identity< Com >)
Definition: Component.h:92
virtual const ComRegistry::Type & comType() const =0
Get type of component.
Holds both a name string and its hashed value, and unlike Id the name is never compiled out...
Definition: Id.h:144
#define error_(msg)
Throw AssertionFailure with a message. Message ignored in final mode.
Definition: Debug.h:44
Type(const String &name, mt::identity< Com > com, mt::identity< SuperCom >)
Definition: Component.h:98
Combined intrusive/non-intrusive smart pointer. Can reference and share any object automatically...
Definition: SharedPtr.h:175
Unrooted acyclic tree.
Definition: Tree.h:17
SharedPtr< const Component > ConstPtr
Definition: Component.h:178
Iter find(Range &&, Seqs &&..., Func &&pred)
Find an element in a series of sequences.
std::enable_if<!b, T > disable_if
Opposite of std::enable_if.
Definition: Meta.h:62
virtual void onComInsert()
Called after component is inserted into ComObj.
Definition: Component.h:202
SharedPtr< Component > Ptr
Definition: Component.h:177
const vector< Type * > & hierarchy() const
Get hierarchy: this type and all supertypes. Base supertype is at front, this type is at back...
Definition: Component.h:102
Type & type(const Id &id) const
Get component type with id.
Definition: Component.h:152
std::enable_if< mt::isIterator< Iter1 >::value, Range_< Iter1, Iter2 > >::type range(Iter1 &&first, Iter2 &&last)
Range from iterators [first, last)
Definition: Range.h:116
ListenerList & listeners()
Get listener list.
Definition: Component.h:195
virtual ~Component()
Definition: Component.h:181
virtual void setInstId(const Id &id)
Override from object, updates ComObject map.
Definition: Component.cpp:57
static mt_global(ComRegistry, inst,)
Get singleton.
static ComRegistry::DepNode createTypeDep()
Called when dep graph is built to determine component type dependencies. May be overridden by subclas...
Definition: Component.h:199
Special void type, use where void is intended but implicit members are required (default ctor...
Definition: Meta.h:37
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
std::enable_if< std::is_default_constructible< Com >::value &&!std::is_abstract< Com >::value, Component & >::type create()
Called by registry to create a component. May be specialized for a component type.
Definition: Component.h:75
Unicode UTF-16 string class, wrapper around std::u16string.
Definition: String.h:23
void reg()
Register a component type.
Definition: Component.h:133
Component()
Definition: Component.h:180
Component & create(const Id &type) const
Create a component from a type.
Definition: Component.h:144
Holds global list of all component types.
Definition: Component.h:82
Base class for components. Components can only be attached to one ComObject at a time.
Definition: Component.h:172
bool isSubtypeOf(const Id &base) const
Returns true if this type is base or inherits from base
Definition: Component.h:107
Component object. Object that consists of a collection of components.
Definition: ComObject.h:17
Returns type T unchanged.
Definition: Meta.h:25
virtual void onComRemove()
Called before component is removed from ComObj.
Definition: Component.h:204
DepGraph< DepNode > DepGraph
Definition: Component.h:126
const DepGraph & depGraph() const
Get dependency graph for all component types.
Definition: Component.h:160
Holds a name string and its hashed value for fast comparison ops. See String Identifier.
Definition: Id.h:25
const String & name() const
Definition: Id.h:155
Base class for objects.
Definition: Object.h:12
Collection of listeners.
Definition: ListenerList.h:16
Global Honeycomb namespace.
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
auto reversed(Range &&range) -> Range_< std::reverse_iterator< mt_iterOf(range)>, std::reverse_iterator< mt_iter_endOf(range)>>
Reverse a range. Begin/End iterators must be bidirectional.
Definition: Range.h:132