SDK:User Data
.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->GetHandleSize( 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.