SDK:User Data

From Vectorworks Developer
Jump to navigation Jump to search

.SDK|SDK ..SDK:Types|SDK Types ..SDK:Using the SDK|Using the SDK ..VCOM:VCOM (Vectorworks Component Object Model)|VCOM Basics ..VCOM:Class Reference|VCOM Class Reference

What is this?

User data is a mechanism for attaching extended user plug-in specific data to any object in the Vectorworks document. Basically you can attach user data to any SDK:MCObjectHandle

User data is nothing more but memory block attached to an object's AUX list.

The interpretation of the user data memory block is fully in the hands of the plug-in developer. Byte swapping is also in the hands of the developer.

User Data objects are identified by Four Char Code (or in other works a Uint32) identifier.

There are the following functions in the SDK related to User Data:

  • ISDK::FindDataObject -- finds the first occurrence of data object inside specified Vectorworks object.
  • ISDK::NextDataObject -- finds the next occurrence of the data object inside specified Vectorworks object after existing data object. Used for enumerating.
  • ISDK::NewDataObject -- creates new user data memory block and attaches it to a specified Vectorworks object.

Sample

Create

Each User Data block is recognized by a Found Char Code (or in other works Sint32) value.

// 1. Define User Data tag ID
#define kDataObjectTag    (OSType) 'MyOB'

// 2. delete any of the data objects that the object may contain
MCObjectHandle	hDataObject = gSDK->FindDataObject( hObject, kDataObjectTag );
while( hDataObject ) {
  gSDK->DeleteAuxObject( hDataObject, hObject );
  hDataObject	= gSDK->FindDataObject( hObject, kDataObjectTag );
}

// 3. create new data object
size_t      dataSize = sizeof(SMyData) + kUserDataTypeSize;
hDataObject          = gSDK->NewDataObject( hObject, kDataObjectTag, dataSize );
if ( hDataObject ) {
  char*	pDataMemory		= * (char**)hDataObject;
  if ( pDataMemory ) {
    // 4. copy the data into the user data memory block
    // offset the reserved data so it will point to the actuall data
    pDataMemory				+= kUserDataTypeSize;
    memcpy( pDataMemory, & fMyData, sizeof(SMyData) );
  }
}
  • 1. Define User Data tag ID
It is important to define constant for your Uint32 (or Four Char Code) identifier.
It is going to be used for recognizing it.
  • 2. Delete any of the data objects that the object may contain
Before creating user data block we want to ensure that there is no user data block with the same ID.
So, we iterate through the data blocks attached to the AUX list of 'hObject'. If we found some, we delete them using ISDK::DeleteAuxObject for deleting AUX list objects.
  • 3. Create new data object
We call ISDK::NewDataObject to allocate memory for the new user data object. Note that this is normal Vectorworks object that has SDK:MCObjectHandle
We have to specify size. The sample keeps its data into 'SMyData' structure, which represents the data that needs to be stored.
So, memory is allocated for the size of that structure, plus additional space required for VectorWorks SDK management. This space is predefined with existing definition kUserDataTypeSize
The creation call actually creates the user data object, and attaches it to the AUX list of the object (hObject)
  • 4. Copy the data into the user data memory block
Once the user data object is created, we access the allocated memory by interpreting the handle to (char**) and getting the memory (char*) from it.
This way we receive the entire object's memory. We need to offset that pointer to the place where out data needs to be. (Failing to do that will result in corrupting Vectorworks specific data that exist at the beginning of this memory block.) The reserved memory block has predefined size kUserDataTypeSize.
Then we just copy our structure that contains the information into the user data memory block.

Read

bool           ok          = false;
// 1. Find the data object inside hObject
MCObjectHandle hDataObject = gSDK->FindDataObject( hObject, kDataObjectTag );
if ( hDataObject ) {
  size_t   handleDataSize  = 0;
  gSDK->GSGetHandleSize( hDataObject, handleDataSize );

  // 2. Get User Data object memory block
  char*	pDataMemory  = * (char**)hDataObject;

  // offset the reserved data so it will point to the actuall data
  pDataMemory     += kUserDataTypeSize;
  handleDataSize  -= kUserDataTypeSize;

  // 3. read the memory
  size_t   copyBlockSize  =  min( sizeof(SMyData), handleDataSize );
  memcpy( & fMyData, pDataMemory, copyBlockSize );
}
  • 1. Find the data object inside hObject
First thing to do is to find the user data object inside 'hObject'.
We are searching for data object with particular ID 'kDataObjectTag'. See creating.
  • 2. Get User Data object memory block
We need to obtain pointer to the data object memory block. The beginning of that memory block is reserved for VectorWorks use, so we need to offset the memory with predefined amount kUserDataTypeSize. See creating.
  • 3. Read the memory
Before reading the memory block we make sure that we wont override memory in our 'fMyData'.
This is part of supporting new and old versions.

The Data

The data stored in this example is contained by the SMyData structure. Note that the example mem-copies the structure which will only work for primitive types. It will not work for classes that have pointers and/or virtual members, like TXString for example.

Here is an example data structure:

struct SMyData
{
    Sint32    fIntegerData;
    double    fRealData;
    char      fFixedSizeString[64];
};

See Also

SDK:The Vectorworks Environment