VR-Forces 4.0.4 Class Documentation
Creating New Interface Content

Table of Contents

Interface messages use DtSimInterfaceContent objects to store the message data.

If you want to create a new interface message, do the following:

  1. Derive a class from DtSimInterfaceContent.
  2. Give it a unique type() string and a clone() function.
  3. Set pertinent parameters.
  4. Create a network representation for the class.
  5. Implement netRepSize(), setFromNet(), and setToNet() to send and retrieve the network representation.
  6. Register the new DtSimInterfaceContent with the DtInterfaceContentFactory. If NewType is an integer constant that corresponds to your type() function, and NewContentClass::creator is a pointer to your creator function, you can change the main.cxx of your front-end and back-end to register the new content as follows:

    // Front-end:
    DtVrfGuiAppEventController::appController()->remoteController()->vrfMessageInterface()->factory()->addCreatorFcn(NewType, NewContentClass::creator);
    // Back-end:
    app.cgf()->factoryManager()->interfaceContentFactory()->addCreatorFcn(NewType, NewContentClass::creator); 
    

  7. Insert it into a DtSimInterfaceMessage.

Implementing the type() and clone() Member Functions

DtSimInterfaceContent is an abstract class. Any derived class must include a type() member function that returns the type of interface message this content is used for. The type() member function has the following specification:

virtual int type() const;

A class derived from DtSimInterfaceContent needs to provide this type() member function, and should provide mutators and accessors for the information (if any) it will convey. A class derived from DtSimInterfaceContent must also provide a clone() member function. The clone() member function is specified as:

virtual DtSimInterface* clone() const;

Clone functions are typically implemented by calling the class’s copy constructor, for example,

MyClass::clone()
{
   return new MyClass(*this);
}

Setting Parameters

If your new message has additional parameters, add class member variables to represent the data. Make sure the clone() function that you define handles the copying of any new member data. Any member variables that you add are copied to or from a network representation for transmission over the network.

Creating the Network Representation

To make the new message capable of being sent over the network, you must provide a network representation for your class. To do this you must serialize all parameters of your message into a character buffer, and then be able to unserialize them back into the class data members.

You may do this in a number of ways, including making a C-style structure using the MAK "Net" types, such as DtNetInt32 (defined in NetTypes.h). These type manage byte order swapping when necessary to ensure platform independence.

VR-Forces also supplies a number of functions in the DtBufferSerialize namespace for serializing data. This is the recommended way of creating the network representation for your new messages.

Note:
If you use a structure, make sure its size is a multiple of 8 bytes to prevent misalignment. You do not need to do this when using DtBufferSerialize.

Implementing netRepSize()

The netRepSize() member function of your class must return the total number of bytes that will be needed to serialize your class in its current state. This may vary depending on the current values of arguments. For example, if you class has a string argument, the size needed to serialize your class will vary depending on the length of the string value.

int MyMessageContent::netRepSize()
{
   int size = 0;
   size += DtBufferSerialize::getSize(myInt);
   size += DtBufferSerialize::getSize(myString);
   return size;
}

Implementing setFromNet()

The setFromNet() function sets class member data from a network buffer. Using the DtBufferSerialize utility member functions, your member function would look something like this:

bool MyMessageContent::setFromNet(const char* contentBuffer, unsigned int contentSize)
{
   contentBuffer = DtBufferSerialize::decode(myInt, contentBuffer);
   contentBuffer = DtBufferSerialize::decode(myString, contentBuffer);
   return true;
}

Implementing setToNet()

The setToNet() function fills in the network representation of the interface content class from the content arguments. This function must call netRep() at the start to allocate the network buffer (myNetRep), if it has not already been created. Using the DtBufferSerialize utility functions, your member function would look like this:

bool MyMessageContent::setToNet()
{
   If (!netRep())
   {
      return false;
   }
   char* buffer = myNetRep;
   buffer = DtBufferSerialize::encode(myInt, buffer);
   buffer = DtBufferSerialize::encode(myString, buffer);
   return true;
}
Note:
It is important that the encode and decode calls be made in the same order in the setFromNet() and setToNet() functions.
Delete the class member myNetRep and set it to NULL any time the size of the net representation changes. If, for example, the length of myStringData changes, delete myNetRep. It will get reallocated to the correct size in setToNet() before it gets used again. Delete myNetRep and set it to NULL in any mutators you create that you know will affect the size of the variable data in the net representation.
For example, if we provide a mutator for myStringData in MyMessageContent:
void MyMessageContent::setString (const DtString& string)
{

   // Set the value in our data member
   myStringData = string;

   // Our string may have changed size and therefore the size of 
   // the network representation may have changed. Delete myNetRep 
   // and set it to NULL. We will recreate it with the correct size 
   // when we need it in setToNet().

   if(myNetRep) {
      delete myNetRep;
      myNetRep = NULL;
   } 
}

[<< Receiving Interface Messages] [Home] [Top of Page] [Message Classes >>]


Document ID: Generated on Fri Jun 29 16:33:32 EDT 2012 from SVN revision 116588
Copyright © 2005-2012 VT MÄK Inc. All Rights Reserved (www.mak.com)