]> git.mxchange.org Git - simgear.git/blobdiff - simgear/hla/HLAObjectInstance.cxx
Merge branch 'timoore/optimizations' into next
[simgear.git] / simgear / hla / HLAObjectInstance.cxx
index 0324d328b54a3584b6f811984e175007867f32af..f1b7fed07a52085103ae06422646bdf6b9f6c28f 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 - 2010  Mathias Froehlich - Mathias.Froehlich@web.de
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Library General Public
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
 
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
+
+#include <simgear/compiler.h>
+
 #include "HLAObjectInstance.hxx"
 
 #include <algorithm>
+#include "simgear/debug/logstream.hxx"
 #include "HLAArrayDataElement.hxx"
 #include "HLABasicDataElement.hxx"
 #include "HLADataElement.hxx"
 #include "HLAEnumeratedDataElement.hxx"
+#include "HLAFederate.hxx"
 #include "HLAFixedRecordDataElement.hxx"
 #include "HLAObjectClass.hxx"
-#include "HLAVariantDataElement.hxx"
+#include "HLAVariantRecordDataElement.hxx"
 #include "RTIObjectClass.hxx"
 #include "RTIObjectInstance.hxx"
 
 namespace simgear {
 
+HLAObjectInstance::UpdateCallback::~UpdateCallback()
+{
+}
+
+HLAObjectInstance::ReflectCallback::~ReflectCallback()
+{
+}
+
 HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass) :
     _objectClass(objectClass)
 {
+    if (objectClass)
+        _federate = objectClass->_federate;
 }
 
-HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass, RTIObjectInstance* rtiObjectInstance) :
-    _objectClass(objectClass),
-    _rtiObjectInstance(rtiObjectInstance)
+HLAObjectInstance::~HLAObjectInstance()
 {
-    _rtiObjectInstance->_hlaObjectInstance = this;
-    _name = _rtiObjectInstance->getName();
+    _clearRTIObjectInstance();
 }
 
-HLAObjectInstance::~HLAObjectInstance()
+const std::string&
+HLAObjectInstance::getName() const
+{
+    return _name;
+}
+
+const SGWeakPtr<HLAFederate>&
+HLAObjectInstance::getFederate() const
 {
+    return _federate;
 }
 
-SGSharedPtr<HLAObjectClass>
+const SGSharedPtr<HLAObjectClass>&
 HLAObjectInstance::getObjectClass() const
 {
-    return _objectClass.lock();
+    return _objectClass;
 }
 
 unsigned
 HLAObjectInstance::getNumAttributes() const
 {
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Trying to get number of attributes for inactive object!");
+    if (!_objectClass.valid())
         return 0;
-    }
-    return _rtiObjectInstance->getNumAttributes();
+    return _objectClass->getNumAttributes();
 }
 
 unsigned
 HLAObjectInstance::getAttributeIndex(const std::string& name) const
 {
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute index for inactive object!");
-        return 0;
-    }
-    return _rtiObjectInstance->getAttributeIndex(name);
+    if (!_objectClass.valid())
+        return ~0u;
+    return _objectClass->getAttributeIndex(name);
 }
 
 std::string
 HLAObjectInstance::getAttributeName(unsigned index) const
 {
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute name for inactive object!");
+    if (!_objectClass.valid())
         return std::string();
-    }
-    return _rtiObjectInstance->getAttributeName(index);
+    return _objectClass->getAttributeName(index);
 }
 
-const HLADataType*
-HLAObjectInstance::getAttributeDataType(unsigned index) const
+bool
+HLAObjectInstance::getAttributeOwned(unsigned index) const
 {
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute index for inactive object!");
-        return 0;
-    }
-    return _rtiObjectInstance->getAttributeDataType(index);
+    if (!_rtiObjectInstance.valid())
+        return false;
+    return _rtiObjectInstance->getAttributeOwned(index);
 }
 
-void
-HLAObjectInstance::setAttributeDataElement(unsigned index, SGSharedPtr<HLADataElement> dataElement)
+const HLADataType*
+HLAObjectInstance::getAttributeDataType(unsigned index) const
 {
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!");
-        return;
-    }
-    _rtiObjectInstance->setDataElement(index, dataElement);
+    if (!_objectClass.valid())
+        return 0;
+    return _objectClass->getAttributeDataType(index);
 }
 
 HLADataElement*
 HLAObjectInstance::getAttributeDataElement(unsigned index)
 {
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!");
+    if (_attributeVector.size() <= index)
         return 0;
-    }
-    return _rtiObjectInstance->getDataElement(index);
+    return _attributeVector[index]._dataElement.get();
 }
 
 const HLADataElement*
 HLAObjectInstance::getAttributeDataElement(unsigned index) const
 {
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!");
+    if (_attributeVector.size() <= index)
         return 0;
+    return _attributeVector[index]._dataElement.get();
+}
+
+bool
+HLAObjectInstance::getAttributeData(unsigned index, RTIData& data) const
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Trying to get raw attribute data without rti object instance for \"" << getName() << "\"!");
+        return false;
     }
-    return _rtiObjectInstance->getDataElement(index);
+    return _rtiObjectInstance->getAttributeData(index, data);
 }
 
-class HLAObjectInstance::DataElementFactoryVisitor : public HLADataTypeVisitor {
+void
+HLAObjectInstance::setAttributeDataElement(unsigned index, const SGSharedPtr<HLADataElement>& dataElement)
+{
+    unsigned numAttributes = getNumAttributes();
+    if (numAttributes <= index)
+        return;
+    _attributeVector.resize(numAttributes);
+    if (_attributeVector[index]._dataElement.valid())
+        _attributeVector[index]._dataElement->clearStamp();
+    _attributeVector[index]._dataElement = dataElement;
+    if (_attributeVector[index]._dataElement.valid())
+        _attributeVector[index]._dataElement->createStamp();
+}
+
+class HLAObjectInstance::DataElementFactoryVisitor : public HLADataElementFactoryVisitor {
 public:
     DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
         _pathElementMap(pathElementMap)
@@ -150,7 +183,7 @@ public:
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLASCharDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAUInt8DataType& dataType)
     {
@@ -158,7 +191,7 @@ public:
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAUCharDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAInt16DataType& dataType)
     {
@@ -166,7 +199,7 @@ public:
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAShortDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAUInt16DataType& dataType)
     {
@@ -174,7 +207,7 @@ public:
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAUShortDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAInt32DataType& dataType)
     {
@@ -182,7 +215,7 @@ public:
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAIntDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAUInt32DataType& dataType)
     {
@@ -190,7 +223,7 @@ public:
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAUIntDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAInt64DataType& dataType)
     {
@@ -198,7 +231,7 @@ public:
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLALongDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAUInt64DataType& dataType)
     {
@@ -206,7 +239,7 @@ public:
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAULongDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAFloat32DataType& dataType)
     {
@@ -214,7 +247,7 @@ public:
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAFloatDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAFloat64DataType& dataType)
     {
@@ -222,7 +255,7 @@ public:
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLADoubleDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
 
     class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
@@ -287,7 +320,7 @@ public:
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAEnumeratedDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
 
     virtual void apply(const HLAFixedRecordDataType& dataType)
@@ -312,9 +345,9 @@ public:
         _dataElement = recordDataElement;
     }
 
-    class VariantDataElementFactory : public HLAVariantDataElement::DataElementFactory {
+    class VariantRecordDataElementFactory : public HLAVariantRecordDataElement::DataElementFactory {
     public:
-        VariantDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
+        VariantRecordDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
             _path(path)
         {
             for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
@@ -325,9 +358,9 @@ public:
                 _pathElementMap.insert(*i);
             }
         }
-        virtual HLADataElement* createElement(const HLAVariantDataElement& element, unsigned index)
+        virtual HLADataElement* createElement(const HLAVariantRecordDataElement& element, unsigned index)
         {
-            const HLAVariantDataType* dataType = element.getDataType();
+            const HLAVariantRecordDataType* dataType = element.getDataType();
             if (!dataType)
                 return 0;
             const HLADataType* alternativeDataType = element.getAlternativeDataType();
@@ -344,22 +377,19 @@ public:
         HLAPathElementMap _pathElementMap;
     };
 
-    virtual void apply(const HLAVariantDataType& dataType)
+    virtual void apply(const HLAVariantRecordDataType& dataType)
     {
         _dataElement = createDataElement(_path, dataType);
         if (_dataElement.valid())
             return;
 
-        SGSharedPtr<HLAVariantDataElement> variantDataElement;
-        variantDataElement = new HLAVariantDataElement(&dataType);
-        variantDataElement->setDataElementFactory(new VariantDataElementFactory(_path, _pathElementMap));
+        SGSharedPtr<HLAVariantRecordDataElement> variantRecordDataElement;
+        variantRecordDataElement = new HLAVariantRecordDataElement(&dataType);
+        variantRecordDataElement->setDataElementFactory(new VariantRecordDataElementFactory(_path, _pathElementMap));
 
-        _dataElement = variantDataElement;
+        _dataElement = variantRecordDataElement;
     }
 
-    const SGSharedPtr<HLADataElement>& getDataElement() const
-    { return _dataElement; }
-
 private:
     SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
     {
@@ -381,7 +411,6 @@ private:
         return dataElement;
     }
 
-    SGSharedPtr<HLADataElement> _dataElement;
     const HLAPathElementMap& _pathElementMap;
     HLADataElement::Path _path;
 };
@@ -391,8 +420,8 @@ HLAObjectInstance::setAttribute(unsigned index, const HLAPathElementMap& pathEle
 {
     const HLADataType* dataType = getAttributeDataType(index);
     if (!dataType) {
-        SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute at index "
-               << index << "!");
+        SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute \""
+               << getAttributeName(index) << "\" at index " << index << "!");
         return;
     }
 
@@ -414,47 +443,37 @@ HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePath
 }
 
 void
-HLAObjectInstance::requestAttributeUpdate(unsigned index)
+HLAObjectInstance::registerInstance()
 {
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Trying to request attribute update for inactive object!");
-        return;
-    }
-    _rtiObjectInstance->setRequestAttributeUpdate(index, true);
+    registerInstance(_objectClass.get());
 }
 
 void
-HLAObjectInstance::requestAttributeUpdate()
-{
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Trying to request attribute update for inactive object!");
-        return;
-    }
-    _rtiObjectInstance->setRequestAttributeUpdate(true);
-}
-
-void
-HLAObjectInstance::registerInstance()
+HLAObjectInstance::registerInstance(HLAObjectClass* objectClass)
 {
     if (_rtiObjectInstance.valid()) {
         SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!");
         return;
     }
-    SGSharedPtr<HLAObjectClass> objectClass = _objectClass.lock();
-    if (!objectClass.valid()) {
+    if (!objectClass) {
         SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!");
         return;
     }
+    if (_objectClass.valid() && objectClass != _objectClass.get()) {
+        SG_LOG(SG_IO, SG_ALERT, "Could not change object class while registering!");
+        return;
+    }
+    _objectClass = objectClass;
+    _federate = _objectClass->_federate;
     // This error must have been flagged before
-    if (!objectClass->_rtiObjectClass.valid())
+    if (!_objectClass->_rtiObjectClass.valid())
         return;
-    _rtiObjectInstance = objectClass->_rtiObjectClass->registerObjectInstance(this);
+    _setRTIObjectInstance(_objectClass->_rtiObjectClass->registerObjectInstance(this));
     if (!_rtiObjectInstance.valid()) {
         SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!");
         return;
     }
-    _name = _rtiObjectInstance->getName();
-    objectClass->registerInstance(*this);
+    _objectClass->_registerInstance(this);
 }
 
 void
@@ -464,81 +483,200 @@ HLAObjectInstance::deleteInstance(const RTIData& tag)
         SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
         return;
     }
-    SGSharedPtr<HLAObjectClass> objectClass = _objectClass.lock();
-    if (!objectClass.valid())
+    if (!_objectClass.valid())
         return;
-    objectClass->deleteInstance(*this);
+    _objectClass->_deleteInstance(*this);
     _rtiObjectInstance->deleteObjectInstance(tag);
 }
 
 void
-HLAObjectInstance::localDeleteInstance()
+HLAObjectInstance::updateAttributeValues(const RTIData& tag)
+{
+    if (_updateCallback.valid()) {
+        _updateCallback->updateAttributeValues(*this, tag);
+    } else {
+        encodeAttributeValues();
+        sendAttributeValues(tag);
+    }
+}
+
+void
+HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
+{
+    if (_updateCallback.valid()) {
+        _updateCallback->updateAttributeValues(*this, timeStamp, tag);
+    } else {
+        encodeAttributeValues();
+        sendAttributeValues(timeStamp, tag);
+    }
+}
+
+void
+HLAObjectInstance::encodeAttributeValues()
+{
+    unsigned numAttributes = _attributeVector.size();
+    for (unsigned i = 0; i < numAttributes;++i) {
+        if (_attributeVector[i]._unconditionalUpdate) {
+            encodeAttributeValue(i);
+        } else if (_attributeVector[i]._enabledUpdate) {
+            const HLADataElement* dataElement = getAttributeDataElement(i);
+            if (dataElement && dataElement->getDirty())
+                encodeAttributeValue(i);
+        }
+    }
+}
+
+void
+HLAObjectInstance::encodeAttributeValue(unsigned index)
 {
     if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
+        SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
         return;
     }
-   _rtiObjectInstance->localDeleteObjectInstance();
+    HLADataElement* dataElement = getAttributeDataElement(index);
+    if (!dataElement)
+        return;
+    _rtiObjectInstance->encodeAttributeData(index, *dataElement);
+    dataElement->setDirty(false);
 }
 
 void
-HLAObjectInstance::updateAttributeValues(const RTIData& tag)
+HLAObjectInstance::sendAttributeValues(const RTIData& tag)
 {
     if (!_rtiObjectInstance.valid()) {
         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
         return;
     }
-    if (_attributeCallback.valid())
-        _attributeCallback->updateAttributeValues(*this, tag);
     _rtiObjectInstance->updateAttributeValues(tag);
 }
 
 void
-HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
+HLAObjectInstance::sendAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
 {
     if (!_rtiObjectInstance.valid()) {
         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
         return;
     }
-    if (_attributeCallback.valid())
-        _attributeCallback->updateAttributeValues(*this, tag);
     _rtiObjectInstance->updateAttributeValues(timeStamp, tag);
 }
 
 void
-HLAObjectInstance::reflectQueuedAttributeValues(const SGTimeStamp& timeStamp)
+HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
 {
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
+    for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
+        reflectAttributeValue(*i, tag);
+}
+
+void
+HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList,
+                                          const SGTimeStamp& timeStamp, const RTIData& tag)
+{
+    for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
+        reflectAttributeValue(*i, timeStamp, tag);
+}
+
+void
+HLAObjectInstance::reflectAttributeValue(unsigned index, const RTIData& tag)
+{
+    HLADataElement* dataElement = getAttributeDataElement(index);
+    if (!dataElement)
         return;
-    }
-    _rtiObjectInstance->reflectQueuedAttributeValues(timeStamp);
+    dataElement->setTimeStampValid(false);
+    _rtiObjectInstance->decodeAttributeData(index, *dataElement);
 }
 
 void
-HLAObjectInstance::removeInstance(const RTIData& tag)
+HLAObjectInstance::reflectAttributeValue(unsigned index, const SGTimeStamp& timeStamp, const RTIData& tag)
 {
-    SGSharedPtr<HLAObjectClass> objectClass = _objectClass.lock();
-    if (!objectClass.valid())
+    HLADataElement* dataElement = getAttributeDataElement(index);
+    if (!dataElement)
         return;
-    objectClass->removeInstanceCallback(*this, tag);
+    dataElement->setTimeStamp(timeStamp);
+    dataElement->setTimeStampValid(true);
+    _rtiObjectInstance->decodeAttributeData(index, *dataElement);
 }
 
 void
-HLAObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag)
+HLAObjectInstance::_setRTIObjectInstance(RTIObjectInstance* rtiObjectInstance)
 {
-    if (!_attributeCallback.valid())
+    if (!_objectClass.valid())
         return;
-    _attributeCallback->reflectAttributeValues(*this, dataPairList, tag);
+
+    _rtiObjectInstance = rtiObjectInstance;
+    _rtiObjectInstance->setObjectInstance(this);
+    _name = _rtiObjectInstance->getName();
+
+    unsigned numAttributes = getNumAttributes();
+    _attributeVector.resize(numAttributes);
+    for (unsigned i = 0; i < numAttributes; ++i) {
+        HLAUpdateType updateType = _objectClass->getAttributeUpdateType(i);
+        if (getAttributeOwned(i) && updateType != HLAUndefinedUpdate) {
+            _attributeVector[i]._enabledUpdate = true;
+            _attributeVector[i]._unconditionalUpdate = (updateType == HLAPeriodicUpdate);
+            // In case of an owned attribute, now encode its value
+            encodeAttributeValue(i);
+        } else {
+            _attributeVector[i]._enabledUpdate = false;
+            _attributeVector[i]._unconditionalUpdate = false;
+        }
+    }
+
+    // This makes sense with any new object. Even if we registered one, there might be unpublished attributes.
+    HLAIndexList indexList;
+    for (unsigned i = 0; i < numAttributes; ++i) {
+        HLAUpdateType updateType = _objectClass->getAttributeUpdateType(i);
+        if (getAttributeOwned(i))
+            continue;
+        if (updateType == HLAUndefinedUpdate)
+            continue;
+        if (updateType == HLAPeriodicUpdate)
+            continue;
+        indexList.push_back(i);
+    }
+    _rtiObjectInstance->requestObjectAttributeValueUpdate(indexList);
 }
 
 void
-HLAObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList,
-                                          const SGTimeStamp& timeStamp, const RTIData& tag)
+HLAObjectInstance::_clearRTIObjectInstance()
+{
+    if (!_rtiObjectInstance.valid())
+        return;
+
+    for (unsigned i = 0; i < _attributeVector.size(); ++i) {
+        _attributeVector[i]._enabledUpdate = false;
+        _attributeVector[i]._unconditionalUpdate = false;
+    }
+
+    _rtiObjectInstance->setObjectInstance(0);
+    _rtiObjectInstance = 0;
+}
+
+void
+HLAObjectInstance::_removeInstance(const RTIData& tag)
 {
-    if (!_attributeCallback.valid())
+    if (!_objectClass.valid())
         return;
-    _attributeCallback->reflectAttributeValues(*this, dataPairList, timeStamp, tag);
+    _objectClass->_removeInstance(*this, tag);
+}
+
+void
+HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
+{
+    if (_reflectCallback.valid()) {
+        _reflectCallback->reflectAttributeValues(*this, indexList, tag);
+    } else {
+        reflectAttributeValues(indexList, tag);
+    }
+}
+
+void
+HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag)
+{
+    if (_reflectCallback.valid()) {
+        _reflectCallback->reflectAttributeValues(*this, indexList, timeStamp, tag);
+    } else {
+        reflectAttributeValues(indexList, timeStamp, tag);
+    }
 }
 
 } // namespace simgear