]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAObjectInstance.cxx
hla: Fixes for the data element index implementation.
[simgear.git] / simgear / hla / HLAObjectInstance.cxx
1 // Copyright (C) 2009 - 2012  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 #ifdef HAVE_CONFIG_H
19 #  include <simgear_config.h>
20 #endif
21
22 #include <simgear/compiler.h>
23
24 #include "HLAObjectInstance.hxx"
25
26 #include <algorithm>
27 #include "simgear/debug/logstream.hxx"
28 #include "HLAArrayDataElement.hxx"
29 #include "HLABasicDataElement.hxx"
30 #include "HLADataElement.hxx"
31 #include "HLAEnumeratedDataElement.hxx"
32 #include "HLAFederate.hxx"
33 #include "HLAFixedRecordDataElement.hxx"
34 #include "HLAObjectClass.hxx"
35 #include "HLAVariantRecordDataElement.hxx"
36 #include "RTIObjectClass.hxx"
37 #include "RTIObjectInstance.hxx"
38
39 namespace simgear {
40
41 HLAObjectInstance::UpdateCallback::~UpdateCallback()
42 {
43 }
44
45 HLAObjectInstance::ReflectCallback::~ReflectCallback()
46 {
47 }
48
49 HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass) :
50     _objectClass(objectClass)
51 {
52     if (objectClass)
53         _federate = objectClass->_federate;
54 }
55
56 HLAObjectInstance::~HLAObjectInstance()
57 {
58     _clearRTIObjectInstance();
59 }
60
61 const std::string&
62 HLAObjectInstance::getName() const
63 {
64     return _name;
65 }
66
67 const SGWeakPtr<HLAFederate>&
68 HLAObjectInstance::getFederate() const
69 {
70     return _federate;
71 }
72
73 const SGSharedPtr<HLAObjectClass>&
74 HLAObjectInstance::getObjectClass() const
75 {
76     return _objectClass;
77 }
78
79 unsigned
80 HLAObjectInstance::getNumAttributes() const
81 {
82     if (!_objectClass.valid())
83         return 0;
84     return _objectClass->getNumAttributes();
85 }
86
87 unsigned
88 HLAObjectInstance::getAttributeIndex(const std::string& name) const
89 {
90     if (!_objectClass.valid())
91         return ~0u;
92     return _objectClass->getAttributeIndex(name);
93 }
94
95 std::string
96 HLAObjectInstance::getAttributeName(unsigned index) const
97 {
98     if (!_objectClass.valid())
99         return std::string();
100     return _objectClass->getAttributeName(index);
101 }
102
103 bool
104 HLAObjectInstance::getAttributeOwned(unsigned index) const
105 {
106     if (!_rtiObjectInstance.valid())
107         return false;
108     return _rtiObjectInstance->getAttributeOwned(index);
109 }
110
111 const HLADataType*
112 HLAObjectInstance::getAttributeDataType(unsigned index) const
113 {
114     if (!_objectClass.valid())
115         return 0;
116     return _objectClass->getAttributeDataType(index);
117 }
118
119 HLADataElement*
120 HLAObjectInstance::getAttributeDataElement(unsigned index)
121 {
122     if (_attributeVector.size() <= index)
123         return 0;
124     return _attributeVector[index]._dataElement.get();
125 }
126
127 const HLADataElement*
128 HLAObjectInstance::getAttributeDataElement(unsigned index) const
129 {
130     if (_attributeVector.size() <= index)
131         return 0;
132     return _attributeVector[index]._dataElement.get();
133 }
134
135 bool
136 HLAObjectInstance::getAttributeData(unsigned index, RTIData& data) const
137 {
138     if (!_rtiObjectInstance.valid()) {
139         SG_LOG(SG_IO, SG_ALERT, "Trying to get raw attribute data without rti object instance for \"" << getName() << "\"!");
140         return false;
141     }
142     return _rtiObjectInstance->getAttributeData(index, data);
143 }
144
145 void
146 HLAObjectInstance::setAttributeDataElement(unsigned index, const SGSharedPtr<HLADataElement>& dataElement)
147 {
148     unsigned numAttributes = getNumAttributes();
149     if (numAttributes <= index)
150         return;
151     _attributeVector.resize(numAttributes);
152     if (_attributeVector[index]._dataElement.valid())
153         _attributeVector[index]._dataElement->clearStamp();
154     _attributeVector[index]._dataElement = dataElement;
155     if (_attributeVector[index]._dataElement.valid())
156         _attributeVector[index]._dataElement->createStamp();
157 }
158
159 class HLAObjectInstance::DataElementFactoryVisitor : public HLADataElementFactoryVisitor {
160 public:
161     DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
162         _pathElementMap(pathElementMap)
163     { }
164     DataElementFactoryVisitor(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
165         _pathElementMap(pathElementMap),
166         _path(path)
167     { }
168     virtual ~DataElementFactoryVisitor() {}
169
170     virtual void apply(const HLADataType& dataType)
171     {
172         _dataElement = createDataElement(_path, dataType);
173         if (_dataElement.valid())
174             return;
175
176         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
177                << dataType.getName() << "\"");
178     }
179
180     virtual void apply(const HLAInt8DataType& dataType)
181     {
182         _dataElement = createDataElement(_path, dataType);
183         if (_dataElement.valid())
184             return;
185
186         HLADataElementFactoryVisitor::apply(dataType);
187     }
188     virtual void apply(const HLAUInt8DataType& dataType)
189     {
190         _dataElement = createDataElement(_path, dataType);
191         if (_dataElement.valid())
192             return;
193
194         HLADataElementFactoryVisitor::apply(dataType);
195     }
196     virtual void apply(const HLAInt16DataType& dataType)
197     {
198         _dataElement = createDataElement(_path, dataType);
199         if (_dataElement.valid())
200             return;
201
202         HLADataElementFactoryVisitor::apply(dataType);
203     }
204     virtual void apply(const HLAUInt16DataType& dataType)
205     {
206         _dataElement = createDataElement(_path, dataType);
207         if (_dataElement.valid())
208             return;
209
210         HLADataElementFactoryVisitor::apply(dataType);
211     }
212     virtual void apply(const HLAInt32DataType& dataType)
213     {
214         _dataElement = createDataElement(_path, dataType);
215         if (_dataElement.valid())
216             return;
217
218         HLADataElementFactoryVisitor::apply(dataType);
219     }
220     virtual void apply(const HLAUInt32DataType& dataType)
221     {
222         _dataElement = createDataElement(_path, dataType);
223         if (_dataElement.valid())
224             return;
225
226         HLADataElementFactoryVisitor::apply(dataType);
227     }
228     virtual void apply(const HLAInt64DataType& dataType)
229     {
230         _dataElement = createDataElement(_path, dataType);
231         if (_dataElement.valid())
232             return;
233
234         HLADataElementFactoryVisitor::apply(dataType);
235     }
236     virtual void apply(const HLAUInt64DataType& dataType)
237     {
238         _dataElement = createDataElement(_path, dataType);
239         if (_dataElement.valid())
240             return;
241
242         HLADataElementFactoryVisitor::apply(dataType);
243     }
244     virtual void apply(const HLAFloat32DataType& dataType)
245     {
246         _dataElement = createDataElement(_path, dataType);
247         if (_dataElement.valid())
248             return;
249
250         HLADataElementFactoryVisitor::apply(dataType);
251     }
252     virtual void apply(const HLAFloat64DataType& dataType)
253     {
254         _dataElement = createDataElement(_path, dataType);
255         if (_dataElement.valid())
256             return;
257
258         HLADataElementFactoryVisitor::apply(dataType);
259     }
260
261     class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
262     public:
263         ArrayDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
264             _path(path)
265         {
266             for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
267                  i != pathElementMap.end(); ++i) {
268                 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
269                                                     path.begin(), path.end()))
270                     break;
271                 _pathElementMap.insert(*i);
272             }
273         }
274         virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
275         {
276             const HLADataType* dataType = element.getElementDataType();
277             if (!dataType)
278                 return 0;
279             HLADataElement::Path path = _path;
280             path.push_back(HLADataElement::PathElement(index));
281             DataElementFactoryVisitor visitor(path, _pathElementMap);
282             dataType->accept(visitor);
283             return visitor._dataElement.release();
284         }
285     private:
286         HLADataElement::Path _path;
287         HLAPathElementMap _pathElementMap;
288     };
289
290     virtual void apply(const HLAFixedArrayDataType& dataType)
291     {
292         _dataElement = createDataElement(_path, dataType);
293         if (_dataElement.valid())
294             return;
295
296         SGSharedPtr<HLAArrayDataElement> arrayDataElement;
297         arrayDataElement = new HLAArrayDataElement(&dataType);
298         arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
299         arrayDataElement->setNumElements(dataType.getNumElements());
300
301         _dataElement = arrayDataElement;
302     }
303
304     virtual void apply(const HLAVariableArrayDataType& dataType)
305     {
306         _dataElement = createDataElement(_path, dataType);
307         if (_dataElement.valid())
308             return;
309
310         SGSharedPtr<HLAArrayDataElement> arrayDataElement;
311         arrayDataElement = new HLAArrayDataElement(&dataType);
312         arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
313
314         _dataElement = arrayDataElement;
315     }
316
317     virtual void apply(const HLAEnumeratedDataType& dataType)
318     {
319         _dataElement = createDataElement(_path, dataType);
320         if (_dataElement.valid())
321             return;
322
323         HLADataElementFactoryVisitor::apply(dataType);
324     }
325
326     virtual void apply(const HLAFixedRecordDataType& dataType)
327     {
328         _dataElement = createDataElement(_path, dataType);
329         if (_dataElement.valid())
330             return;
331
332         SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
333         recordDataElement = new HLAFixedRecordDataElement(&dataType);
334
335         unsigned numFields = dataType.getNumFields();
336         for (unsigned i = 0; i < numFields; ++i) {
337
338             _path.push_back(HLADataElement::PathElement(dataType.getFieldName(i)));
339
340             dataType.getFieldDataType(i)->accept(*this);
341             recordDataElement->setField(i, _dataElement.release());
342
343             _path.pop_back();
344         }
345         _dataElement = recordDataElement;
346     }
347
348     class VariantRecordDataElementFactory : public HLAVariantRecordDataElement::DataElementFactory {
349     public:
350         VariantRecordDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
351             _path(path)
352         {
353             for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
354                  i != pathElementMap.end(); ++i) {
355                 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
356                                                     path.begin(), path.end()))
357                     break;
358                 _pathElementMap.insert(*i);
359             }
360         }
361         virtual HLADataElement* createElement(const HLAVariantRecordDataElement& element, unsigned index)
362         {
363             const HLAVariantRecordDataType* dataType = element.getDataType();
364             if (!dataType)
365                 return 0;
366             const HLADataType* alternativeDataType = element.getAlternativeDataType();
367             if (!alternativeDataType)
368                 return 0;
369             HLADataElement::Path path = _path;
370             path.push_back(HLADataElement::PathElement(dataType->getAlternativeName(index)));
371             DataElementFactoryVisitor visitor(path, _pathElementMap);
372             alternativeDataType->accept(visitor);
373             return visitor._dataElement.release();
374         }
375     private:
376         HLADataElement::Path _path;
377         HLAPathElementMap _pathElementMap;
378     };
379
380     virtual void apply(const HLAVariantRecordDataType& dataType)
381     {
382         _dataElement = createDataElement(_path, dataType);
383         if (_dataElement.valid())
384             return;
385
386         SGSharedPtr<HLAVariantRecordDataElement> variantRecordDataElement;
387         variantRecordDataElement = new HLAVariantRecordDataElement(&dataType);
388         variantRecordDataElement->setDataElementFactory(new VariantRecordDataElementFactory(_path, _pathElementMap));
389
390         _dataElement = variantRecordDataElement;
391     }
392
393 private:
394     SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
395     {
396         HLAPathElementMap::const_iterator i = _pathElementMap.find(path);
397         if (i == _pathElementMap.end()) {
398             SG_LOG(SG_IO, SG_WARN, "No dataElement provided for \""
399                    << HLADataElement::toString(path) << "\".");
400
401             return 0;
402         }
403         SGSharedPtr<HLADataElement> dataElement = i->second.getDataElement(path);
404         if (!dataElement->setDataType(&dataType)) {
405             SG_LOG(SG_IO, SG_ALERT, "Cannot set data type for data element at \""
406                    << HLADataElement::toString(path) <<  "\"!");
407             return 0;
408         }
409         SG_LOG(SG_IO, SG_DEBUG, "Using provided dataElement for \""
410                << HLADataElement::toString(path) << "\".");
411         return dataElement;
412     }
413
414     const HLAPathElementMap& _pathElementMap;
415     HLADataElement::Path _path;
416 };
417
418 void
419 HLAObjectInstance::setAttribute(unsigned index, const HLAPathElementMap& pathElementMap)
420 {
421     const HLADataType* dataType = getAttributeDataType(index);
422     if (!dataType) {
423         SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute \""
424                << getAttributeName(index) << "\" at index " << index << "!");
425         return;
426     }
427
428     SG_LOG(SG_IO, SG_DEBUG, "Setting DataElement for attribute \""
429            << getAttributeName(index) << "\".");
430
431     DataElementFactoryVisitor visitor(pathElementMap);
432     dataType->accept(visitor);
433     setAttributeDataElement(index, visitor.getDataElement());
434 }
435
436 void
437 HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePathElementMap)
438 {
439     for (HLAAttributePathElementMap::const_iterator i = attributePathElementMap.begin();
440          i != attributePathElementMap.end(); ++i) {
441         setAttribute(i->first, i->second);
442     }
443 }
444
445 bool
446 HLAObjectInstance::getDataElementIndex(HLADataElementIndex& index, const std::string& path) const
447 {
448     HLAObjectClass* objectClass = getObjectClass().get();
449     if (!objectClass) {
450         SG_LOG(SG_IO, SG_ALERT, "Could not get the data element index of an object instance with unknown class!");
451         return false;
452     }
453     return objectClass->getDataElementIndex(index, path);
454 }
455
456 HLADataElementIndex
457 HLAObjectInstance::getDataElementIndex(const std::string& path) const
458 {
459     HLADataElementIndex dataElementIndex;
460     getDataElementIndex(dataElementIndex, path);
461     return dataElementIndex;
462 }
463
464 HLADataElement*
465 HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index)
466 {
467     if (index.empty())
468         return 0;
469     HLADataElement* dataElement = getAttributeDataElement(index[0]);
470     if (!dataElement)
471         return 0;
472     return dataElement->getDataElement(index.begin() + 1, index.end());
473 }
474
475 const HLADataElement*
476 HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index) const
477 {
478     if (index.empty())
479         return 0;
480     const HLADataElement* dataElement = getAttributeDataElement(index[0]);
481     if (!dataElement)
482         return 0;
483     return dataElement->getDataElement(index.begin() + 1, index.end());
484 }
485
486 void
487 HLAObjectInstance::setAttributeDataElement(const HLADataElementIndex& index, const SGSharedPtr<HLADataElement>& dataElement)
488 {
489     if (index.empty())
490         return;
491     if (index.size() == 1) {
492         if (!getAttributeDataType(index[0]))
493             return;
494         if (dataElement.valid() && !dataElement->setDataType(getAttributeDataType(index[0])))
495             return;
496         setAttributeDataElement(index[0], dataElement);
497     } else {
498         SGSharedPtr<HLADataElement> attributeDataElement = getAttributeDataElement(index[0]);
499         if (!attributeDataElement.valid()) {
500             createAndSetAttributeDataElement(index[0]);
501             attributeDataElement = getAttributeDataElement(index[0]);
502         }
503         if (!attributeDataElement.valid())
504             return;
505         attributeDataElement->setDataElement(index.begin() + 1, index.end(), dataElement.get());
506     }
507 }
508
509 HLADataElement*
510 HLAObjectInstance::getAttributeDataElement(const std::string& path)
511 {
512     HLADataElementIndex index;
513     if (!getDataElementIndex(index, path))
514         return 0;
515     return getAttributeDataElement(index); 
516 }
517
518 const HLADataElement*
519 HLAObjectInstance::getAttributeDataElement(const std::string& path) const
520 {
521     HLADataElementIndex index;
522     if (!getDataElementIndex(index, path))
523         return 0;
524     return getAttributeDataElement(index); 
525 }
526
527 void
528 HLAObjectInstance::setAttributeDataElement(const std::string& path, const SGSharedPtr<HLADataElement>& dataElement)
529 {
530     HLADataElementIndex index;
531     if (!getDataElementIndex(index, path))
532         return;
533     setAttributeDataElement(index, dataElement); 
534 }
535
536 void
537 HLAObjectInstance::discoverInstance(const RTIData& tag)
538 {
539     HLAObjectClass* objectClass = getObjectClass().get();
540     if (!objectClass) {
541         SG_LOG(SG_IO, SG_ALERT, "Could not discover instance of unknown object class!");
542         return;
543     }
544     objectClass->discoverInstance(*this, tag);
545 }
546
547 void
548 HLAObjectInstance::removeInstance(const RTIData& tag)
549 {
550     HLAObjectClass* objectClass = getObjectClass().get();
551     if (!objectClass) {
552         SG_LOG(SG_IO, SG_ALERT, "Could not remove instance of unknown object class!");
553         return;
554     }
555     objectClass->removeInstance(*this, tag);
556 }
557
558 void
559 HLAObjectInstance::registerInstance()
560 {
561     registerInstance(_objectClass.get());
562 }
563
564 void
565 HLAObjectInstance::registerInstance(HLAObjectClass* objectClass)
566 {
567     if (_rtiObjectInstance.valid()) {
568         SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!");
569         return;
570     }
571     if (!objectClass) {
572         SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!");
573         return;
574     }
575     if (_objectClass.valid() && objectClass != _objectClass.get()) {
576         SG_LOG(SG_IO, SG_ALERT, "Could not change object class while registering!");
577         return;
578     }
579     _objectClass = objectClass;
580     _federate = _objectClass->_federate;
581     // This error must have been flagged before
582     if (!_objectClass->_rtiObjectClass.valid())
583         return;
584     _setRTIObjectInstance(_objectClass->_rtiObjectClass->registerObjectInstance(this));
585     if (!_rtiObjectInstance.valid()) {
586         SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!");
587         return;
588     }
589     _objectClass->_registerInstance(this);
590 }
591
592 void
593 HLAObjectInstance::deleteInstance(const RTIData& tag)
594 {
595     if (!_rtiObjectInstance.valid()) {
596         SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
597         return;
598     }
599     if (!_objectClass.valid())
600         return;
601     _objectClass->_deleteInstance(*this);
602     _rtiObjectInstance->deleteObjectInstance(tag);
603 }
604
605 void
606 HLAObjectInstance::createAttributeDataElements()
607 {
608     HLAObjectClass* objectClass = getObjectClass().get();
609     if (!objectClass) {
610         SG_LOG(SG_IO, SG_ALERT, "Could not create data elements for instance of unknown object class!");
611         return;
612     }
613     objectClass->createAttributeDataElements(*this);
614 }
615
616 void
617 HLAObjectInstance::createAndSetAttributeDataElement(unsigned index)
618 {
619     if (getAttributeDataElement(index)) {
620         SG_LOG(SG_IO, SG_DEBUG, "Attribute data element for attribute \""
621                << getAttributeName(index) << "\" is already set.");
622         return;
623     }
624     SGSharedPtr<HLADataElement> dataElement = createAttributeDataElement(index);
625     setAttributeDataElement(index, dataElement);
626 }
627
628 HLADataElement*
629 HLAObjectInstance::createAttributeDataElement(unsigned index)
630 {
631     HLAObjectClass* objectClass = getObjectClass().get();
632     if (!objectClass) {
633         SG_LOG(SG_IO, SG_ALERT, "Could not create data element for instance of unknown object class!");
634         return 0;
635     }
636     return objectClass->createAttributeDataElement(*this, index);
637 }
638
639 void
640 HLAObjectInstance::updateAttributeValues(const RTIData& tag)
641 {
642     if (_updateCallback.valid()) {
643         _updateCallback->updateAttributeValues(*this, tag);
644     } else {
645         encodeAttributeValues();
646         sendAttributeValues(tag);
647     }
648 }
649
650 void
651 HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
652 {
653     if (_updateCallback.valid()) {
654         _updateCallback->updateAttributeValues(*this, timeStamp, tag);
655     } else {
656         encodeAttributeValues();
657         sendAttributeValues(timeStamp, tag);
658     }
659 }
660
661 void
662 HLAObjectInstance::encodeAttributeValues()
663 {
664     unsigned numAttributes = _attributeVector.size();
665     for (unsigned i = 0; i < numAttributes;++i) {
666         if (_attributeVector[i]._unconditionalUpdate) {
667             encodeAttributeValue(i);
668         } else if (_attributeVector[i]._enabledUpdate) {
669             const HLADataElement* dataElement = getAttributeDataElement(i);
670             if (dataElement && dataElement->getDirty())
671                 encodeAttributeValue(i);
672         }
673     }
674 }
675
676 void
677 HLAObjectInstance::encodeAttributeValue(unsigned index)
678 {
679     if (!_rtiObjectInstance.valid()) {
680         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
681         return;
682     }
683     HLADataElement* dataElement = getAttributeDataElement(index);
684     if (!dataElement)
685         return;
686     _rtiObjectInstance->encodeAttributeData(index, *dataElement);
687     dataElement->setDirty(false);
688 }
689
690 void
691 HLAObjectInstance::sendAttributeValues(const RTIData& tag)
692 {
693     if (!_rtiObjectInstance.valid()) {
694         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
695         return;
696     }
697     _rtiObjectInstance->updateAttributeValues(tag);
698 }
699
700 void
701 HLAObjectInstance::sendAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
702 {
703     if (!_rtiObjectInstance.valid()) {
704         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
705         return;
706     }
707     _rtiObjectInstance->updateAttributeValues(timeStamp, tag);
708 }
709
710 void
711 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
712 {
713     for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
714         reflectAttributeValue(*i, tag);
715 }
716
717 void
718 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList,
719                                           const SGTimeStamp& timeStamp, const RTIData& tag)
720 {
721     for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
722         reflectAttributeValue(*i, timeStamp, tag);
723 }
724
725 void
726 HLAObjectInstance::reflectAttributeValue(unsigned index, const RTIData& tag)
727 {
728     HLADataElement* dataElement = getAttributeDataElement(index);
729     if (!dataElement)
730         return;
731     dataElement->setTimeStampValid(false);
732     _rtiObjectInstance->decodeAttributeData(index, *dataElement);
733 }
734
735 void
736 HLAObjectInstance::reflectAttributeValue(unsigned index, const SGTimeStamp& timeStamp, const RTIData& tag)
737 {
738     HLADataElement* dataElement = getAttributeDataElement(index);
739     if (!dataElement)
740         return;
741     dataElement->setTimeStamp(timeStamp);
742     dataElement->setTimeStampValid(true);
743     _rtiObjectInstance->decodeAttributeData(index, *dataElement);
744 }
745
746 void
747 HLAObjectInstance::_setRTIObjectInstance(RTIObjectInstance* rtiObjectInstance)
748 {
749     if (!_objectClass.valid())
750         return;
751
752     _rtiObjectInstance = rtiObjectInstance;
753     _rtiObjectInstance->setObjectInstance(this);
754     _name = _rtiObjectInstance->getName();
755
756     unsigned numAttributes = getNumAttributes();
757     _attributeVector.resize(numAttributes);
758     for (unsigned i = 0; i < numAttributes; ++i) {
759         HLAUpdateType updateType = _objectClass->getAttributeUpdateType(i);
760         if (getAttributeOwned(i) && updateType != HLAUndefinedUpdate) {
761             _attributeVector[i]._enabledUpdate = true;
762             _attributeVector[i]._unconditionalUpdate = (updateType == HLAPeriodicUpdate);
763             // In case of an owned attribute, now encode its value
764             encodeAttributeValue(i);
765         } else {
766             _attributeVector[i]._enabledUpdate = false;
767             _attributeVector[i]._unconditionalUpdate = false;
768         }
769     }
770
771     // This makes sense with any new object. Even if we registered one, there might be unpublished attributes.
772     HLAIndexList indexList;
773     for (unsigned i = 0; i < numAttributes; ++i) {
774         HLAUpdateType updateType = _objectClass->getAttributeUpdateType(i);
775         if (getAttributeOwned(i))
776             continue;
777         if (updateType == HLAUndefinedUpdate)
778             continue;
779         if (updateType == HLAPeriodicUpdate)
780             continue;
781         indexList.push_back(i);
782     }
783     _rtiObjectInstance->requestObjectAttributeValueUpdate(indexList);
784 }
785
786 void
787 HLAObjectInstance::_clearRTIObjectInstance()
788 {
789     if (!_rtiObjectInstance.valid())
790         return;
791
792     for (unsigned i = 0; i < _attributeVector.size(); ++i) {
793         _attributeVector[i]._enabledUpdate = false;
794         _attributeVector[i]._unconditionalUpdate = false;
795     }
796
797     _rtiObjectInstance->setObjectInstance(0);
798     _rtiObjectInstance = 0;
799 }
800
801 void
802 HLAObjectInstance::_removeInstance(const RTIData& tag)
803 {
804     if (!_objectClass.valid())
805         return;
806     _objectClass->_removeInstance(*this, tag);
807 }
808
809 void
810 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
811 {
812     if (_reflectCallback.valid()) {
813         _reflectCallback->reflectAttributeValues(*this, indexList, tag);
814     } else {
815         reflectAttributeValues(indexList, tag);
816     }
817 }
818
819 void
820 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag)
821 {
822     if (_reflectCallback.valid()) {
823         _reflectCallback->reflectAttributeValues(*this, indexList, timeStamp, tag);
824     } else {
825         reflectAttributeValues(indexList, timeStamp, tag);
826     }
827 }
828
829 } // namespace simgear