3DXI Property Containers

Each IExportEntity stored in the 3DXI database supports IPropertyContainer. This interface is responsible for finding the properties on the entity. It loops through the various places where parameter blocks can be stored, gathering custom object data and custom attributes, if applicable. Developers should request this interface if they want to access any plug-in specific parameters.

Generic 3DXI objects (IGameGenObject) also provide access to IPropertyContainer using the function IGameGenObject::GetIPropertyContainer().

IPropertyContainer provides two ways to extract parameters from parameter blocks maintained by plugins, or IGameObject:

Both these methods supply individual parameter data wrapped in in IGameProperty. Which method to follow depends on the level of control and the amount of data to extract.

For example: the query-by-name route supplies all parameter block parameters, as well as custom attributes and custom object data that is assigned in the Object Properties dialog of a 3ds Max object. Custom attributes and MAXScript scripted plugins are also supported in the manner. Developers can specify the name of the file to be used when initializing the game export interfaces, thus allowing specific data to be maintained.

Query by Name

All properties are collected and accessed by name. The name parameter is corresponding to the MAXScript property name of the object. It provides easy way to identify data available. In MAXScript listener object properties can be listed with ShowProperties() call permitting the developer to query the property by name.

Given a pointer to an IPropertyContainer interface a developer could write a wrapper function as follows:

IPropertyContainer * pc = material->GetIPropertyContainer ();
IGameProperty * prop = pc->QueryPropery(_T("Ambient"));

The important aspect of the XML-based extraction is that custom object data can be exported and represented as an IGameProperty. Once the data is defined, it can be accessed in the exact same way as any other property.

Custom object data can be seen in the following listing:

- <ExportUserData>
- <!--
 Accessto the Node User Data
 - <!--
 Theid mustbe uniqueto the file
- <UserProperty>
<id>101</id>
<simplename>IGameTestString</simplename>
  <keyName>IGameTestString</keyName>
  <type>string</type>
  </UserProperty>
  </ExportUserData>

Note that the only difference between an IGameProperty object returning a User Property is that the controller interface will be NULL.

Simple Enumeration

Any IExportEntity can have its parameters enumerated. The developer simply registers a callback for the IPropertyContainer to use, and then every parameter-block based parameter found will be returned to the developer through the callback.

The 3DXI export sample (\\samples\igame\export) uses this technique to export the names of every property found on an object. This includes modifiers, materials or anything that supports the IPropertyContainer interface. The following code sample shows how to setup the callback.

class MyProc : public PropertyEnum
{
    DumpProperties * dp;

 public:
    MyProc(DumpProperties * d) {dp = d;}
    bool Proc(IGameProperty * prop)
    {
        TCHAR Buf[256];
        _tcscpy(Buf,prop->GetName());

        // if it is null, this is usually because its a IParamBlock and it is
        // not animated, thus No name
        if(_tcscmp(Buf, _T(""))!=0){
             //use the Property here
        }
        return false; //lets keep going
    }
};

The callback is set using the following code where material is a pointer to an IGameMaterial object.

IPropertyContainer *pCont = material->GetIPropertyContainer();
MyProc * proccy = newMyProc(this);
pCont->EnumerateProperties(proccy);

This method will provide access to every parameter that was found during the initialization process. The technique is useful if you want to access the underlying parameter block for any parameter and thus provide read and write access to the data. This is also the quickest way to obtain parameters from the various entities. The developer is responsible for accessing the parameter block in the correct manner using the main 3ds Max SDK if they decide to use the kind of low level access.