5.5 Generic Attributes

All entities can embed an arbitrary number of generic attributes. They can be accessed from any A3DRootBase instance.

Reading or writing generic attributes involves several steps and a good knowledge on attributes hierarchy:

This page is a general presentation on how to read attributes from any A3DRootBase instance.

Reading a single attribute instance

A single attribute is an instance of A3DMiscSingleAttributeData, a data-only structure which is described as:

typedef struct
{
A3DUns16 m_usStructSize;
A3DBool m_bTitleIsInt;
A3DUTF8Char* m_pcTitle;
A3DUTF8Char* m_pcData;
A3DUns16 m_usUnit;

Any attribute is a Title/Value pair where:

  • The Title is either a c-string or an integer.
  • The data is any of the above mentioned type.

Reading the title

The title of an attribute is stored in the m_pcTitle attribute and its type depends on m_bTitleIsInt. According to its value the title encodes either a 32-bit unsigned integer or a c-string.

void ReadSingleAttributeTitle(const A3DMiscSingleAttributeData* in_sAttr)
{
if(in_sAttr.m_bTitleIsInt == A3D_TRUE)
{
A3DUns32 uiTitle;
memcpy(&uiTitle, in_sAttr.m_pcTitle, sizeof(A3DUns32));
printf("Title: %d", uiTitle);
}
else
{
const A3DUTF8Char* pcTitle = in_sAttr.m_pcTitle;
printf("Title: %s", pcTitle);
}
}

This example code outputs the attribute title according to its type.

32-bit integer data

If m_eType == kA3DModellerAttributeTypeInt the data is stored as a 32-bit integer data (A3DUns32):

{
A3DUns32 uiData;
memcpy(&uiData, in_sAttr.m_pcData, sizeof(A3DUns32));
printf("Value: %d", uiData);
}

32-bit floating point

If m_eType == kA3DModellerAttributeTypeInt the data is stored as a 32-bit floating point data (A3DFloat):

{
A3DFloat uiData;
memcpy(&uiData, in_sAttr.m_pcData, sizeof(A3DFloat));
printf("Value: %f", uiData);
}

When the value is a floating-point the field m_usUnit is used to specify a unit for this value. If no unit is provided, m_usUnit is set to A3D_DEFAULT_NO_UNIT.

For more information about generic unit specifiers, see the unit attributes page.

UTF-8 c-string

If m_eType == kA3DModellerAttributeTypeString the data is stored as a null-terminated UTF-8 string (A3DUTF8Char*):

{
A3DUTF8Char* pcData = in_sAttr.m_pcData;
printf("Value: %s", uiData);
}

Time specifier

If m_eType == kA3DModellerAttributeTypeTime the data is stored as a time specifier as defined by the `time_t` specifications:

{
time_t iData;
memcpy(&iData, in_sAttr.m_pcData, sizeof(A3DInt32));
printf("Value: %s", asctime(gmtime(&iData)));
}

Reading an attribute

An attribute is an instance of A3DMiscAttribute. Any attribute has a title and zero or more A3DMiscSingleAttributeData:

void ReadAttribute(const A3DMiscAttribute* in_pAttribute)
{
A3DMiscAttributeData sAttributeData;
A3DMiscAttributeGet(in_pAttribute, &sAttributeData);
// Iterate through the single attributes
const A3DUns32 uiNSingleAttributes = sAttributeData.m_uiSize;
fo(A3DUns32 sa = 0 ; sa < uiNSingleAttributes ; ++sa)
{
const A3DMiscSingleAttributeData* pSingleAttributeData = sAttributeData.m_asSingleAttributesData + sa;
ReadSingleAttribute(pSingleAttributeData);
}
A3DMiscAttributeGet(NULL, &sAttributeData);
}

Getting the list of attributes

Generic attributes of an A3DRootBase instance are available as an array:

void ReadAttributes(const A3DRootBase* in_pBase)
{
A3DRootBaseData sRootBaseData;
A3DRootBaseGet(in_pBase, &sRootBaseData);
// Iterate through the attributes
const A3DUns32 uiNAttributes = sRootBaseData.m_uiSize;
for(A3DUns32 a = 0 ; a < uiNAttributes ; ++a)
{
const A3DMiscAttribute* pAttribute = sRootBaseData.m_ppAttributes[a];
ReadAttribute(pAttribute);
}
A3DRootBaseGet(NULL, &sRootBaseData);
}

All attributes are instances of A3DMiscAttribute.

A Complete Example

The code below is a complete example which traverses an A3DRootBase instance and print all its attributes in the standard output in the form:

// Displays attributes as follow:
// Attribute Title0:
// SingleAttribute Title00: Value (Type): Value00
// SingleAttribute Title01: Value (Type): Value01
// Attribute Title1:
// SingleAttribute Title10: Value (Type): Value10
// SingleAttribute Title11: Value (Type): Value11
// ...
void PrintGenericAttributes(const A3DRootBase* in_pRootBase)
{
A3DRootBaseData sRootBaseData;
A3DRootBaseGet(in_pRootBase, &sRootBaseData);
// Iterate through the attributes
const A3DUns32 uiNAttributes = sRootBaseData.m_uiSize;
for (A3DUns32 a = 0; a < uiNAttributes; ++a)
{
const A3DMiscAttribute* pAttribute = sRootBaseData.m_ppAttributes[a];
A3DMiscAttributeData sAttributeData;
A3DMiscAttributeGet(pAttribute, &sAttributeData);
// Display the attribute title
if (sAttributeData.m_bTitleIsInt == A3D_TRUE)
{
printf("Attribute %d:\n", *((A3DUns32*)sAttributeData.m_pcTitle));
}
else
{
printf("Attribute '%s':\n", sAttributeData.m_pcTitle);
}
// Iterate through the single attributes
const A3DUns32 uiNSingleAttributes = sAttributeData.m_uiSize;
for (A3DUns32 sa = 0; sa < uiNSingleAttributes; ++sa)
{
A3DMiscSingleAttributeData* pSingleAttribute = sAttributeData.m_asSingleAttributesData+sa;
// Display the single attribute title
if (pSingleAttribute->m_bTitleIsInt == A3D_TRUE)
{
printf("Single Attribute %d: ", *((A3DUns32*)pSingleAttribute->m_pcTitle));
}
else
{
printf("Single Attribute '%s': ", pSingleAttribute->m_pcTitle);
}
// Display the single attribute value on the same line
switch (pSingleAttribute->m_eType)
{
printf("Value (A3DUns32): %d\n", *(A3DUns32*)pSingleAttribute->m_pcData);
break;
printf("Value (A3DFloat): %f\n", *(A3DFloat*)pSingleAttribute->m_pcData);
break;
printf("Value (Time): %s\n", asctime(gmtime((time_t*)pSingleAttribute->m_pcData)));
break;
printf("Value (String): %s\n", pSingleAttribute->m_pcData);
break;
default:
break;
}
printf("\n");
}
A3DMiscAttributeGet(NULL, &sAttributeData);
}
A3DRootBaseGet(NULL, &sRootBaseData);
}