vrecko
virtual reality framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
IOPins.h
Go to the documentation of this file.
1 #ifndef IOPINS_H
2 #define IOPINS_H
3 
4 #include <vrecko/Export>
5 #include <vrecko/Message.h>
6 #include <vrecko/BaseClass.h>
7 #include <vrecko/World.h>
8 
9 namespace vrecko {
10 
11 class BaseClass;
12 class Ability;
13 class EnvironmentObject;
14 
15 
16 template <class _MessageType>
17 class InputPin : public InputPinBase {
18 public:
19  typedef void (BaseClass::*PROCESSING_METHOD) (_MessageType *message);
20 
21  InputPin(BaseClass *_owner, const char *_inputName, PROCESSING_METHOD _methodForProcessing) { coreInit(_owner, _inputName, _methodForProcessing); }
23  }
24 
25  virtual VreckoMessage* createCompatibleMessage() { return new _MessageType; }
26 
27  virtual void processMessage(VreckoMessage *message) { if (methodForProcessing) { (owner->*methodForProcessing)((_MessageType*)message); } }
28 
29 protected:
30  void coreInit(BaseClass *_owner, const char *_inputName, PROCESSING_METHOD _methodForProcessing) {
31  owner = _owner;
32  pinName = _inputName;
33  methodForProcessing = _methodForProcessing;
34  }
35 
37 };
38 
39 
40 template <class _MessageType>
41 class OutputPin : public OutputPinBase {
42 public:
43  OutputPin(BaseClass *_owner, const char *_outputName) {
44  owner = _owner;
45  pinName = _outputName;
46  }
47 
49  }
50 
51  virtual VreckoMessage* createCompatibleMessage() { return new _MessageType; }
52 
53  inline bool send(_MessageType *messageToBeSent, EventType eventType = EXPRESS_EVENT) {
54  if (senderStringWithOutputName.empty()) {
55  // first-time initialization (caching the result)
57  }
58  return world->getEventDispatcherPtr()->reportEvent(senderStringWithOutputName, messageToBeSent, eventType);
59  }
60 
61 protected:
62  std::string senderStringWithOutputName; // initialized after the first call to send()
63 };
64 
65 
66 
67 
68 template <class _MessageType, class _ReturningMessageType>
70 public:
71  typedef osg::ref_ptr<_ReturningMessageType> (BaseClass::*PROCESSING_METHOD) (_MessageType *message);
72 
73  RequestInputPin(BaseClass *_owner, const char *_requestInputName, PROCESSING_METHOD _methodForProcessing) { coreInit(_owner, _requestInputName, _methodForProcessing); }
74 
76  }
77 
78  virtual VreckoMessage* createCompatibleMessage() { return new _MessageType; }
79  virtual VreckoMessage* createReturningCompatibleMessage() { return new _ReturningMessageType; }
80 
81  virtual osg::ref_ptr<VreckoMessage> processRequest(VreckoMessage *message) { return (!methodForProcessing) ? NULL : (owner->*methodForProcessing)((_MessageType*)message); }
82 // inline const PROCESSING_METHOD getMethodForProcessing() const { return methodForProcessing; }
83 
84 protected:
85  void coreInit(BaseClass *_owner, const char *_requestInputName, PROCESSING_METHOD _methodForProcessing) {
86  owner = _owner;
87  pinName = _requestInputName;
88  methodForProcessing = _methodForProcessing;
89  }
90 
92 };
93 
94 
95 
96 
97 template <class _MessageType, class _ReturningMessageType>
99 public:
100  RequestOutputPin(BaseClass *_owner, const char *_requestOutputName) {
101  owner = _owner;
102  pinName = _requestOutputName;
103  }
104 
106  }
107 
108  virtual VreckoMessage* createCompatibleMessage() { return new _MessageType; }
109  virtual VreckoMessage* createReturningCompatibleMessage() { return new _ReturningMessageType; }
110 
111  inline osg::ref_ptr<_ReturningMessageType> request(_MessageType *messageToBeSent) {
112  if (senderStringWithOutputName.empty()) {
113  // first-time initialization (caching the result)
115  }
116  return (_ReturningMessageType*)(world->getEventDispatcherPtr()->request(senderStringWithOutputName, messageToBeSent).get());
117  }
118 
119 protected:
120  std::string senderStringWithOutputName; // initialized after the first call to send()
121 };
122 
123 
124 
125 
126 // Explicit instantiation of pins for usual messages.
127 // This is not necessary and also it increases the size of vrecko.lib, but other
128 // do not need to compile it, just overtake the compiled form from the vrecko.lib library.
129 // (I hope I did this right as I don't know how to verify it.)
130 template class VRECKO_EXPORT OutputPin<MessageBool>;
131 template class VRECKO_EXPORT InputPin<MessageBool>;
132 
133 template class VRECKO_EXPORT OutputPin<MessageInt>;
134 template class VRECKO_EXPORT InputPin<MessageInt>;
135 
136 template class VRECKO_EXPORT OutputPin<MessageUnsignedInt>;
137 template class VRECKO_EXPORT InputPin<MessageUnsignedInt>;
138 
139 template class VRECKO_EXPORT OutputPin<MessageFloat>;
140 template class VRECKO_EXPORT InputPin<MessageFloat>;
141 
142 template class VRECKO_EXPORT OutputPin<MessageObjectID>;
143 template class VRECKO_EXPORT InputPin<MessageObjectID>;
144 
145 template class VRECKO_EXPORT OutputPin<MessageString>;
146 template class VRECKO_EXPORT InputPin<MessageString>;
147 
148 template class VRECKO_EXPORT OutputPin<MessageVec2>;
149 template class VRECKO_EXPORT InputPin<MessageVec2>;
150 
151 template class VRECKO_EXPORT OutputPin<MessageVec3>;
152 template class VRECKO_EXPORT InputPin<MessageVec3>;
153 
154 template class VRECKO_EXPORT OutputPin<MessageVec4>;
155 template class VRECKO_EXPORT InputPin<MessageVec4>;
156 
157 template class VRECKO_EXPORT OutputPin<MessageQuat>;
158 template class VRECKO_EXPORT InputPin<MessageQuat>;
159 
160 template class VRECKO_EXPORT OutputPin<MessageMatrix>;
161 template class VRECKO_EXPORT InputPin<MessageMatrix>;
162 
163 
164 
165 
166 
167 // Macros for single-line definition
168 // DELARE_INPUT should be in the header file (.h)
169 #define DECLARE_INPUT(name, message_type) \
170  osg::ref_ptr<vrecko::InputPin<message_type>> input##name; \
171  void onMessage##name(message_type *message);
172 
173 // INIT_INPUT should come in the .cpp file
174 #define INIT_INPUT_EXTNAME(name, message_type, yourClassName, extName) \
175  addInputPin(input##name = new vrecko::InputPin<message_type>(this, extName, (vrecko::InputPin<message_type>::PROCESSING_METHOD)&yourClassName::onMessage##name));
176  // TODO: In newer compilers, this _might_ be solvable without "yourClassname" AND also without "message_type"
177  // by using something like
178  // (decltype(input##name)::PROCESSING_METHOD)&decltype(*this)::onMessage##name
179  // It fails in VC2010, because decltype(*this) infers a class type of Class& and not Class as we need.
180  // We need an rvalue reference for "this", but it doesn't seem to be supported as of yet (May 2011).
181  // See this table:
182  // http://blogs.msdn.com/b/vcblog/archive/2010/04/06/c-0x-core-language-features-in-vc10-the-table.aspx
183  // Solution to exactly this problem is already in the working paper of C++0x (from March 2010)
184  // http://en.wikipedia.org/wiki/Decltype (search for "decltype(v)::value_type" )
185 #define INIT_INPUT(name, message_type, yourClassName) \
186  INIT_INPUT_EXTNAME(name, message_type, yourClassName, #name)
187 
188 #define UNINIT_INPUT(name) \
189  { \
190  if (input##name) { \
191  removeInputPin(input##name); \
192  input##name = NULL; \
193  } \
194  }
195 
196 #define METHOD_INPUT(name, message_type, yourClassName) \
197  void yourClassName::onMessage##name(message_type *message)
198 
199 
200 
201 
202 #define DECLARE_OUTPUT(name, message_type) \
203  osg::ref_ptr<vrecko::OutputPin<message_type>> output##name;
204 
205 #define INIT_OUTPUT_EXTNAME(name, message_type, extName) \
206  addOutputPin(output##name = new vrecko::OutputPin<message_type>(this, extName));
207 
208 #define INIT_OUTPUT(name, message_type) INIT_OUTPUT_EXTNAME(name, message_type, #name)
209 
210 #define UNINIT_OUTPUT(name) \
211  { \
212  if (output##name) { \
213  removeOutputPin(output##name); \
214  output##name = NULL; \
215  } \
216  }
217 
218 
219 
220 
221 #define DECLARE_REQUEST_INPUT(name, message_type, returning_message_type) \
222  osg::ref_ptr<vrecko::RequestInputPin<message_type, returning_message_type>> reqInput##name; \
223  osg::ref_ptr<returning_message_type> onRequest##name(message_type *message);
224 
225 #define INIT_REQUEST_INPUT_EXTNAME(name, message_type, returning_message_type, yourClassName, extName) \
226  addRequestInputPin(reqInput##name = new vrecko::RequestInputPin<message_type, returning_message_type>(this, extName, (vrecko::RequestInputPin<message_type, returning_message_type>::PROCESSING_METHOD)&yourClassName::onRequest##name));
227 
228 #define INIT_REQUEST_INPUT(name, message_type, returning_message_type, yourClassName) \
229  INIT_REQUEST_INPUT_EXTNAME(name, message_type, returning_message_type, yourClassName, #name)
230 
231 #define UNINIT_REQUEST_INPUT(name) \
232  { \
233  if (reqInput##name) { \
234  removeRequestInputPin(reqInput##name); \
235  reqInput##name = NULL; \
236  } \
237  }
238 
239 #define METHOD_REQUEST_INPUT(name, message_type, returning_message_type, yourClassName) \
240  osg::ref_ptr<returning_message_type> yourClassName::onRequest##name(message_type *message)
241 
242 
243 
244 #define DECLARE_REQUEST_OUTPUT(name, message_type, returning_message_type) \
245  osg::ref_ptr<vrecko::RequestOutputPin<message_type, returning_message_type>> reqOutput##name;
246 
247 #define INIT_REQUEST_OUTPUT_EXTNAME(name, message_type, returning_message_type, extName) \
248  addRequestOutputPin(reqOutput##name = new vrecko::RequestOutputPin<message_type, returning_message_type>(this, extName));
249 
250 #define INIT_REQUEST_OUTPUT(name, message_type, returning_message_type) \
251  INIT_REQUEST_OUTPUT_EXTNAME(name, message_type, returning_message_type, #name)
252 
253 #define UNINIT_REQUEST_OUTPUT(name) \
254  { \
255  if (reqOutput##name) { \
256  removeRequestOutputPin(reqOutput##name); \
257  reqOutput##name = NULL; \
258  } \
259  }
260 
261 
262 };
263 
264 #endif