]> git.mxchange.org Git - simgear.git/blob - simgear/hla/RTIObjectInstance.hxx
hla: add missing file fir the last commit.
[simgear.git] / simgear / hla / RTIObjectInstance.hxx
1 // Copyright (C) 2009 - 2010  Mathias Froehlich - Mathias.Froehlich@web.de
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 //
17
18 #ifndef RTIObjectInstance_hxx
19 #define RTIObjectInstance_hxx
20
21 #include <list>
22 #include <map>
23 #include <string>
24 #include <vector>
25 #include "simgear/debug/logstream.hxx"
26 #include "simgear/structure/SGReferenced.hxx"
27 #include "simgear/structure/SGWeakPtr.hxx"
28 #include "simgear/timing/timestamp.hxx"
29 #include "RTIData.hxx"
30 #include "RTIObjectClass.hxx"
31 #include "HLADataElement.hxx"
32
33 class SGTimeStamp;
34
35 namespace simgear {
36
37 class RTIObjectClass;
38 class HLAObjectInstance;
39
40 class RTIObjectInstance : public SGReferenced {
41 public:
42     RTIObjectInstance(HLAObjectInstance* hlaObjectInstance);
43     virtual ~RTIObjectInstance();
44
45     virtual const RTIObjectClass* getObjectClass() const = 0;
46
47     virtual std::string getName() const = 0;
48
49     unsigned getNumAttributes() const;
50     unsigned getAttributeIndex(const std::string& name) const;
51     std::string getAttributeName(unsigned index) const;
52
53     virtual void deleteObjectInstance(const RTIData& tag) = 0;
54     virtual void deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag) = 0;
55     virtual void localDeleteObjectInstance() = 0;
56
57     virtual void requestObjectAttributeValueUpdate() = 0;
58
59     virtual void updateAttributeValues(const RTIData& tag) = 0;
60     virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) = 0;
61
62     void removeInstance(const RTIData& tag);
63     // Call this if you want to roll up the queued timestamed updates
64     // and reflect that into the attached data elements.
65     void reflectQueuedAttributeValues(const SGTimeStamp& timeStamp)
66     {
67         // replay all updates up to the given timestamp
68         UpdateListMap::iterator last = _updateListMap.upper_bound(timeStamp);
69         for (UpdateListMap::iterator i = _updateListMap.begin(); i != last; ++i) {
70             for (UpdateList::iterator j = i->second.begin(); j != i->second.end(); ++j) {
71                 // FIXME have a variant that takes the timestamp?
72                 reflectAttributeValues(j->_indexDataPairList, j->_tag);
73             }
74             putUpdateToPool(i->second);
75         }
76     }
77     void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag);
78     void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const SGTimeStamp& timeStamp, const RTIData& tag);
79     void reflectAttributeValue(unsigned i, const RTIData& data)
80     {
81         if (_attributeData.size() <= i)
82             return;
83         HLADataElement* dataElement = _attributeData[i]._dataElement.get();
84         if (!dataElement)
85             return;
86         HLADecodeStream stream(data);
87         dataElement->decode(stream);
88     }
89
90     const HLADataType* getAttributeDataType(unsigned i) const
91     {
92         return getObjectClass()->getAttributeDataType(i);
93     }
94     HLAUpdateType getAttributeUpdateType(unsigned i) const
95     {
96         return getObjectClass()->getAttributeUpdateType(i);
97     }
98     bool getAttributeSubscribed(unsigned i) const
99     {
100         return getObjectClass()->getAttributeSubscribed(i);
101     }
102     bool getAttributePublished(unsigned i) const
103     {
104         return getObjectClass()->getAttributePublished(i);
105     }
106
107     HLADataElement* getDataElement(unsigned i)
108     {
109         if (_attributeData.size() <= i)
110             return 0;
111         return _attributeData[i]._dataElement.get();
112     }
113     const HLADataElement* getDataElement(unsigned i) const
114     {
115         if (_attributeData.size() <= i)
116             return 0;
117         return _attributeData[i]._dataElement.get();
118     }
119     void setDataElement(unsigned i, HLADataElement* dataElement)
120     {
121         if (_attributeData.size() <= i)
122             return;
123         _attributeData[i]._dataElement = dataElement;
124     }
125
126     void updateAttributesFromClass(bool owned)
127     {
128         // FIXME: rethink that!!!
129         unsigned numAttributes = getNumAttributes();
130         unsigned i = 0;
131         for (; i < _attributeData.size(); ++i) {
132             if (getAttributePublished(i)) {
133             } else {
134                 _attributeData[i].setUpdateEnabled(false);
135                 _attributeData[i].setOwned(false);
136             }
137         }
138         _attributeData.resize(numAttributes);
139         for (; i < numAttributes; ++i) {
140             if (getAttributePublished(i)) {
141                 _attributeData[i].setUpdateEnabled(true);
142                 _attributeData[i].setOwned(owned);
143             } else {
144                 _attributeData[i].setUpdateEnabled(false);
145                 _attributeData[i].setOwned(false);
146             }
147         }
148     }
149
150     void setAttributeForceUpdate(unsigned i)
151     {
152         if (_attributeData.size() <= i)
153             return;
154         _attributeData[i].setForceUpdate(true);
155     }
156     void setAttributeInScope(unsigned i, bool inScope)
157     {
158         if (_attributeData.size() <= i)
159             return;
160         _attributeData[i].setInScope(inScope);
161     }
162     void setAttributeUpdateEnabled(unsigned i, bool enabled)
163     {
164         if (_attributeData.size() <= i)
165             return;
166         _attributeData[i].setUpdateEnabled(enabled);
167     }
168     void setAttributeUpdated(unsigned i)
169     {
170         if (_attributeData.size() <= i)
171             return;
172         _attributeData[i].setForceUpdate(false);
173     }
174     bool getAttributeEffectiveUpdateEnabled(unsigned i)
175     {
176         if (_attributeData.size() <= i)
177             return false;
178         if (!getAttributePublished(i))
179             return false;
180         if (!_attributeData[i]._updateEnabled)
181             return false;
182         if (!_attributeData[i]._inScope)
183             return false;
184         if (_attributeData[i]._forceUpdate)
185             return true;
186         switch (getAttributeUpdateType(i)) {
187         case HLAPeriodicUpdate:
188             return true;
189         case HLAConditionalUpdate:
190             return true; // FIXME
191         case HLAStaticUpdate:
192             return false;
193         default:
194             return false;
195         }
196     }
197     void setRequestAttributeUpdate(bool request)
198     {
199         for (unsigned i = 0; i < getNumAttributes(); ++i) {
200             if (getAttributeUpdateType(i) == HLAPeriodicUpdate)
201                 continue;
202             setRequestAttributeUpdate(i, request);
203         }
204     }
205     void setRequestAttributeUpdate(unsigned i, bool request)
206     {
207         if (_attributeData.size() <= i)
208             return;
209         _attributeData[i].setRequestUpdate(request);
210         if (request) {
211             if (!_pendingAttributeUpdateRequest) {
212                 _pendingAttributeUpdateRequest = true;
213             }
214         }
215     }
216     bool getRequestAttributeUpdate(unsigned i) const
217     {
218         if (_attributeData.size() <= i)
219             return false;
220         return _attributeData[i]._requestUpdate;
221     }
222
223     void flushPendingRequests()
224     {
225         if (_pendingAttributeUpdateRequest) {
226             requestObjectAttributeValueUpdate();
227             _pendingAttributeUpdateRequest = false;
228         }
229     }
230
231 protected:
232     // The backward reference to the user visible object
233     SGWeakPtr<HLAObjectInstance> _hlaObjectInstance;
234
235     // Is true if we should emit a requestattr
236     bool _pendingAttributeUpdateRequest;
237
238     // Contains a full update as it came in from the RTI
239     struct Update {
240         RTIIndexDataPairList _indexDataPairList;
241         RTIData _tag;
242     };
243     // A bunch of updates for the same timestamp
244     typedef std::list<Update> UpdateList;
245     // The timestamp sorted list of updates
246     typedef std::map<SGTimeStamp, UpdateList> UpdateListMap;
247
248     // The timestamped updates sorted by timestamp
249     UpdateListMap _updateListMap;
250
251     // The pool of unused updates so that we do not need to malloc/free each time
252     UpdateList _updateList;
253
254     void getUpdateFromPool(UpdateList& updateList)
255     {
256         if (_updateList.empty())
257             updateList.push_back(Update());
258         else
259             updateList.splice(updateList.end(), _updateList, _updateList.begin());
260     }
261     void putUpdateToPool(UpdateList& updateList)
262     {
263         for (UpdateList::iterator i = updateList.begin(); i != updateList.end(); ++i)
264             putDataToPool(i->_indexDataPairList);
265         _updateList.splice(_updateList.end(), updateList);
266     }
267
268     // Appends the updates in the list to the given timestamps updates
269     void scheduleUpdates(const SGTimeStamp& timeStamp, UpdateList& updateList)
270     {
271         UpdateListMap::iterator i = _updateListMap.find(timeStamp);
272         if (i == _updateListMap.end())
273             i = _updateListMap.insert(UpdateListMap::value_type(timeStamp, UpdateList())).first;
274         i->second.splice(i->second.end(), updateList);
275     }
276
277     // This adds raw storage for attribute index i to the end of the dataPairList.
278     void getDataFromPool(unsigned i, RTIIndexDataPairList& dataPairList)
279     {
280         if (_attributeData.size() <= i) {
281             SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!");
282             return;
283         }
284
285         // Nothing left in the pool - so allocate something
286         if (_attributeData[i]._indexDataPairList.empty()) {
287             dataPairList.push_back(RTIIndexDataPairList::value_type());
288             dataPairList.back().first = i;
289             return;
290         }
291
292         // Take one from the pool
293         dataPairList.splice(dataPairList.end(),
294                             _attributeData[i]._indexDataPairList,
295                             _attributeData[i]._indexDataPairList.begin());
296     }
297
298     void putDataToPool(RTIIndexDataPairList& dataPairList)
299     {
300         while (!dataPairList.empty()) {
301             // Put back into the pool
302             unsigned i = dataPairList.front().first;
303             if (_attributeData.size() <= i) {
304                 // should not happen!!!
305                 SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!");
306                 dataPairList.pop_front();
307             } else {
308                 _attributeData[i]._indexDataPairList.splice(_attributeData[i]._indexDataPairList.begin(),
309                                                             dataPairList, dataPairList.begin());
310             }
311         }
312     }
313
314     struct AttributeData {
315         AttributeData() : _owned(false), _inScope(true), _updateEnabled(true), _forceUpdate(false), _requestUpdate(false)
316         { }
317
318         // The hla level data element with tha actual local program
319         // accessible data.
320         SGSharedPtr<HLADataElement> _dataElement;
321         // SGSharedPtr<HLADataElement::TimeStamp> _timeStamp;
322
323         // Pool of already allocated raw data used for reflection of updates
324         RTIIndexDataPairList _indexDataPairList;
325
326         void setOwned(bool owned)
327         { _owned = owned; }
328         void setInScope(bool inScope)
329         { _inScope = inScope; }
330         void setUpdateEnabled(bool updateEnabled)
331         { _updateEnabled = updateEnabled; }
332         void setForceUpdate(bool forceUpdate)
333         { _forceUpdate = forceUpdate; }
334         void setRequestUpdate(bool requestUpdate)
335         { _requestUpdate = requestUpdate; }
336
337         bool _owned;
338         bool _inScope;
339         bool _updateEnabled;
340         bool _forceUpdate;
341         bool _requestUpdate;
342     };
343     std::vector<AttributeData> _attributeData;
344
345     friend class HLAObjectInstance;
346 };
347
348 }
349
350 #endif