Builds an index of element ID's to (DIS/RPR FOM) marking text.
The DtDataBank contains simulation-specific and element-specific data elements. However there is substantial overlap - VR-Link driver's Marking Text is an element (that comes from that driver) Display Name. Element Data is, for the most part, static, and created when the Element itself is created. Simulation Data, on the other hand, contains both static and dynamic data.
The element data is easier to work with and faster/cheaper to retrieve. In addition to the the already existing Display Name attribute, there is now a Connection ID attribute and a Connection Entity Type attribute. These are whatever a particular connection uses for an ID and entity type, in string form. For example, an element from a DIS connection might have a connection ID of "3001:1:1" and a connection entity type of "1:225:1:1:1:0:0". An element created by a CIGI connection, on the other hand, might have an connection ID of "5" and a connection Entity Type of "17".
It is common for users who are used to working in a DIS or HLA environment to want to look up elements by a connection ID or Marking Text, for example. Connection objects makes that much easier to do.
The exampleElementAttributesPlugin example shows the signal that is raised with all the elements whose attribute data has been received that frame; elements can be added to indices or sets based on attribute data at that time. It builds an index of element IDs to Marking Text (Display Name) and vice versa. The example can easily be extended to build similar indices using connection ID attributes.
This example is a plug-in. You can run it by running ./bin64/exampleElementAttributesPlugin_stealth.bat (on Windows) or ./bin64/exampleElementAttributesPlugin_stealth.sh (on Linux). Load the Ala Moana terrain, once Vantage is started, connect with DIS. Open MAK DIS Logger and load "HawaiiTour-2019-DIS.lgr". Hit Play and you will see the connection information printed in the console. For more information about running examples, please see Running Applications and Examples.
#include <iostream>
namespace makVrv
{
: DtVirtualBaseClass()
, myDe(de)
{
&DtElementAttributesMonitor::slot_elementsInitialized, this, std::placeholders::_1));
mySignalConnections += elements.signal_elementsToBeRemoved.connect(
std::bind(
&DtElementAttributesMonitor::slot_elementsRemoved, this, std::placeholders::_1));
}
DtElementAttributesMonitor::~DtElementAttributesMonitor()
{
}
void DtElementAttributesMonitor::processElementInitialized(
DtElementID entity)
{
if (!entry)
{
std::string displayName = "Unnamed";
attrMgr.getElementDisplayName(entity, displayName);
std::cout << "Invalid Element ID received: " << std::hex << entity << " - "
<< " not found" << std::endl;
return;
}
std::cout << "Added ";
std::string displayName;
if (attrMgr.getElementDisplayName(*entry, displayName))
{
std::cout << displayName;
}
else
{
std::cout << "Unnamed (" << std::hex << entity << ")";
}
std::string driverType;
if (attrMgr.getElementDriverType(*entry, driverType))
{
std::cout << " from " << driverType << std::endl;
}
else
{
std::cout << std::endl;
}
DtElementEntry::ElementType elementType = attrMgr.elementType(*entry);
std::string elementTypeStr = elementTypeToString(elementType);
std::cout << " Element Type " << elementTypeStr << std::endl;
std::string objectId;
if (attrMgr.getElementObjectId(*entry, objectId))
{
std::cout << " Connection ID " << objectId << std::endl;
}
std::string objectType;
if (attrMgr.getElementObjectType(*entry, objectType))
{
std::cout << " Connection Type " << objectType << std::endl;
}
DtElementAttributes::ElementSubtypes subtype;
if (attrMgr.getElementSubtype(*entry, subtype))
{
std::string subtypeStr = elementSubTypeToString(subtype);
std::cout << " Subtype " << subtypeStr << std::endl;
}
DtUnicode elementDefName;
if (attrMgr.getElementElementDefinitionName(*entry, elementDefName))
{
std::string elementDefStr;
elementDefName.toAscii(elementDefStr);
std::cout << " Element Definition " << elementDefStr << std::endl;
}
}
void DtElementAttributesMonitor::processElementRemoved(
DtElementID entity)
{
std::cout << "Removed " << std::hex << entity << " - ";
std::string displayName;
if (attrMgr.getElementDisplayName(entity, displayName))
{
std::cout << displayName << std::endl;
}
else
{
DtElementEntry::ElementType elementType = attrMgr.
elementType(entity);
std::string elementTypeStr = elementTypeToString(elementType);
std::cout << "Unnamed " << elementTypeStr << " (" << entity << ")" << std::endl;
}
}
void DtElementAttributesMonitor::slot_elementsInitialized(const DtElementData::ElementIdList& elements)
{
DtElementData::ElementIdList::const_iterator curIter = elements.begin();
DtElementData::ElementIdList::const_iterator endIter = elements.end();
for (; curIter != endIter; ++curIter)
{
processElementInitialized(*curIter);
}
}
void DtElementAttributesMonitor::slot_elementsRemoved(const DtElementData::ElementIdList& elements)
{
DtElementData::ElementIdList::const_iterator curIter = elements.begin();
DtElementData::ElementIdList::const_iterator endIter = elements.end();
for (; curIter != endIter; ++curIter)
{
processElementRemoved(*curIter);
}
}
void DtElementAttributesMonitor::dumpElements()
{
std::string elementName;
attrMgr.startNamedElementIteration();
while (attrMgr.getNextElementIdAndDisplayName(elementId, elementName))
{
std::cout << "ID: " << std::hex << elementId << " NAME: " << elementName << std::endl;
}
}
std::string DtElementAttributesMonitor::elementTypeToString(DtElementEntry::ElementType elementType)
{
std::string elementTypeStr;
switch (elementType)
{
case DtElementEntry::Unknown:
default:
elementTypeStr = "Unknown";
break;
elementTypeStr = "Entity";
break;
elementTypeStr = "Prop";
break;
case DtElementEntry::TerrainPatch:
elementTypeStr = "Terrain Patch";
break;
case DtElementEntry::Aggregate:
elementTypeStr = "Aggregate";
break;
case DtElementEntry::Observer:
elementTypeStr = "Observer";
break;
case DtElementEntry::Environmental:
elementTypeStr = "Environmental";
break;
case DtElementEntry::GraphicPoint:
elementTypeStr = "Graphic Point";
break;
case DtElementEntry::GraphicShape:
elementTypeStr = "Graphic Shape";
break;
case DtElementEntry::GraphicVertex:
elementTypeStr = "Graphic Vertex";
break;
case DtElementEntry::RemoteGraphic:
elementTypeStr = "Remote Graphic";
break;
case DtElementEntry::TacticalGraphic:
elementTypeStr = "Tactical Graphic";
break;
case DtElementEntry::Intervisibility:
elementTypeStr = "Intervisibility";
break;
case DtElementEntry::Feature:
elementTypeStr = "Feature";
break;
case DtElementEntry::TacticalSmoke:
elementTypeStr = "Tactical Smoke";
break;
case DtElementEntry::BuoyOrBeacon:
elementTypeStr = "Bouy Or Beacon";
break;
case DtElementEntry::DynamicTerrain:
elementTypeStr = "Dynamic Terrain";
break;
}
return elementTypeStr;
}
std::string DtElementAttributesMonitor::elementSubTypeToString(DtElementAttributes::ElementSubtypes subType)
{
std::string subtypeStr;
switch (subType)
{
case DtElementAttributes::FriendlyMunitions:
case DtElementAttributes::OpposingMunitions:
case DtElementAttributes::NeutralMunitions:
case DtElementAttributes::OtherMunitions:
subtypeStr = "Munitions";
break;
case DtElementAttributes::Friendly:
subtypeStr = "Friendly";
break;
case DtElementAttributes::Opposing:
subtypeStr = "Opposing";
break;
case DtElementAttributes::Other:
subtypeStr = "Other";
break;
case DtElementAttributes::Neutral:
subtypeStr = "Neutral";
break;
default:
subtypeStr = "Unrecognized!";
break;
}
return subtypeStr;
}
}