Writing the Device DriverCreating the Device Driver
When you create the library file for your device driver, there are a few things that you need to think about:
You need to retrieve information from the connected device in order to make the device drive something in Softimage. To do this, you can use one of the following strategies according to your needs and style:
Device drivers can contain many channels with data that are continuously being refreshed. For this reason, you should cache the device information to maximize your driver's performance.
For example, you can cache the channel object when the driver is activated. For details on how to do this, see the Mouse Driver example under the mousedriver directory in the SDK example directory.
To hook into Softimage, use the device callbacks listed in the table below.
The Mouse driver plug-in uses the mouse's position to drive the X and Y position. This example illustrates how to use the tools mentioned above to create your device driver.
<factory_path>\XSISDK\examples\drivers\MouseDriverExample: using the XSIDeviceOnActivate callback
If you look at the source code for the Mouse driver, it uses the XSIDeviceOnActivate callback to set up the coordinates for the mouse's position.
extern "C" HRESULT WINAPI XSIDeviceOnActivate() { ApplicationPtr l_pApp; l_pApp.CreateInstance("XSI.Application"); #ifdef DEBUG l_pApp->LogMessage(L"Connecting Mouse Device...", siInfo); #endif //----------------------------------------------------- // Get the mouse position //----------------------------------------------------- POINT l_ptClientMousePos; ::GetCursorPos( &l_ptClientMousePos ); //----------------------------------------------------- //----------------------------------------------------- if (g_pDeviceinfo.m_pChannelX == 0 || g_pDeviceinfo.m_pChannelY ==0) { // here is where the information from the device is initialized // (the actual code that goes here appears in below) } //----------------------------------------------------- // Start a timer using the parameter named : // PollingInterval (20 msec by default) //----------------------------------------------------- #ifdef _TIMER_BASED_EXAMPLE ULONG l_ulPollingInterval = 20; m_idTimer = ::SetTimer( NULL, 1, l_ulPollingInterval, (TIMERPROC)fnTimerProc ) ; #endif g_currentHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)MyMouseProc, g_hInstance,0); return S_OK; }
Example: using a timer loop (instead of an event)
The timer loop forces the driver to periodically refresh the information:
VOID CALLBACK fnTimerProc( HWND /*hwnd*/, UINT /*uMsg*/, UINT /*idEvent*/, DWORD /*dwTime*/ ) { ApplicationPtr l_pApp; l_pApp.CreateInstance("XSI.Application"); //----------------------------------------------------- // Get the mouse position //----------------------------------------------------- POINT l_ptClientMousePos; ::GetCursorPos( &l_ptClientMousePos ); // Set the X channel CComVariant l_varX( (DOUBLE)l_ptClientMousePos.x ); CComVariant l_varY( (DOUBLE)l_ptClientMousePos.y ); g_pDeviceinfo.m_pChannelX->put_Value( l_varX ); g_pDeviceinfo.m_pChannelY->put_Value( l_varY ); }
Example: using an event (instead of a timer loop)
The Mouse driver example also illustrates how to use an event procedure to update the information
LRESULT CALLBACK MyMouseProc ( int nCode, // hook code WPARAM wParam, // message identifier LPARAM lParam // mouse coordinates ) { if (wParam == WM_MOUSEMOVE) { MOUSEHOOKSTRUCT *l_sMouseInfo = (MOUSEHOOKSTRUCT *)lParam; if (g_pDeviceinfo.m_pChannelX) { // Set the X an Y channels CComVariant l_varX( (DOUBLE)l_sMouseInfo->pt.x ); CComVariant l_varY( (DOUBLE)l_sMouseInfo->pt.y ); g_pDeviceinfo.m_pChannelX->put_Value( l_varX ); g_pDeviceinfo.m_pChannelY->put_Value( l_varY ); } } else if (wParam == WM_LBUTTONDOWN) { if (g_pDeviceinfo.m_pChannelLB) { // Trigger the command on the Left Button g_pDeviceinfo.m_pChannelLB->put_Value( CComVariant(1) ); } } else if (wParam == WM_MBUTTONDOWN) { if (g_pDeviceinfo.m_pChannelMB) { // Trigger the command on the Middle Button g_pDeviceinfo.m_pChannelMB->put_Value( CComVariant(1) ); } } else if (wParam == WM_RBUTTONDOWN) { if (g_pDeviceinfo.m_pChannelRB) { // Trigger the command on the Right Button g_pDeviceinfo.m_pChannelRB->put_Value( CComVariant(1) ); } } return CallNextHookEx(g_currentHook,nCode,wParam,lParam); }
Example: caching your device information
You can create a global instance of the device information, which caches the channel objects so you don't have to get new ones for each mouse message:
static _DeviceInfo g_pDeviceinfo;
To add options to your device driver
Users can click the Options button on the device driver window to access the options you set up. To create add options to your device driver plug-in:
Create a custom parameter set that contains the set of options you want to make available to your device driver. For more information on how to create custom parameter sets, see the Animation guide.
In the .xsidevice file, specify the filename (including the path) of the options custom parameter set in the <OptionsPreset> tag.
When the device driver is instantiated, a new custom parameter set is created and nested under the device driver.
When you write your device driver plug-in you can use the object model to access the options values. For more information on how to use the object model to access custom parameter sets, see Working with Parameters.
Accessing Device Drivers through the Object Model
The Softimage object model contains these objects:
The Device object represents a device driver in Softimage. In the User Interface, device drivers are accessible through the Device Manager, which you can open with ToolsDevices on the Animate toolbar.
The DeviceCollection gives access to all device drivers in Softimage. This is the scripting equivalent of the Device Manager, in which you can activate or deactivate a device, add or remove devices, etc.
The Channel object represents the wire between a device and its input into Softimage. Each device driver has a set of channels and each channel can drive something different in the scene.
The ChannelCollection gives access to all channels in the device.
For more information on the specifics of each device driver object and their functions, see the Commands and Scripting Reference.
To illustrate how to use the COM API, you can return to the Mouse driver example.
Example: getting the device driver information
You need to get pointers to the Application, the ChannelCollection, and the Device objects:
HRESULT l_hr; XSIApplicationPtr l_xsiApp(l_pApp); ChannelCollectionPtr l_pChannels; DevicePtr l_pDevice; // Get the DeviceCollection from the Application DeviceCollectionPtr l_pDeviceManager; l_hr = l_xsiApp->get_Devices(&l_pDeviceManager); AssertAndReturn(l_hr); // Get the "Mouse" Device object l_hr = l_pDeviceManager->get_Item( CComVariant(L"Mouse"), &l_pDevice ); AssertAndReturn(l_hr); // Get all channels in the Mouse device l_hr = l_pDevice->get_Channels( &l_pChannels ); AssertAndReturn(l_hr);
Example: getting the information for all channels
Once you have all the channels for a device, you can enumerate the collection to get each member:
// Iterate through all channels in the Mouse device l_hr = l_pChannels->get_Item( CComVariant(0), &g_pDeviceinfo.m_pChannelX); AssertAndReturn(l_hr); l_hr = l_pChannels->get_Item( CComVariant(1), &g_pDeviceinfo.m_pChannelY); AssertAndReturn(l_hr); l_hr = l_pChannels->get_Item( CComVariant(2), &g_pDeviceinfo.m_pChannelLB); AssertAndReturn(l_hr); l_hr = l_pChannels->get_Item( CComVariant(3), &g_pDeviceinfo.m_pChannelMB); AssertAndReturn(l_hr); l_hr = l_pChannels->get_Item( CComVariant(4), &g_pDeviceinfo.m_pChannelRB); AssertAndReturn(l_hr);
Example: getting the information for a specific channel
You can use the Channel ID to get the channel, which is faster than iterating the entire collection:
l_hr = l_pDevice->get_Channel( 1, &g_pDeviceinfo.m_pChannelX); AssertAndReturn(l_hr); l_hr = l_pDevice->get_Channel( 2, &g_pDeviceinfo.m_pChannelY); AssertAndReturn(l_hr);
You may want to create some extra files that can help support your driver in Softimage, such as:
Device presets—you can specify values in a preset so that they load by default. For example, you can create a preset that has a channel with Command specified for the Action field and the name of the command or procedure specified for the Target field.
For more information on how to save and load presets, see the Softimage user guidethe Softimage user guide.
Option custom property sets—you can create a custom property set that contains lists of special options for the device. When available, these options appear on the options window for your device, which the user can open by clicking the Options button on the Device Manager window.
For more information, see To add options to your device driver.
Help files—you may also want to create a web page or a help file for users to explain the functionality of your device driver. In this case, you will need to include your HTML or WinHelp files with your library, .xsidevice, preset, and SPDL files when you distribute your device.
Communicating the Device Information to Softimage
Communicating the Device Information to Softimage
Softimage builds a set of device drivers based on the information that you provide in the .xsidevice file. When Softimage starts, it reads the .xsidevice file and creates a device driver for each device specified.
Understanding the XML device description file
When you want to tell Softimage about the device you want to use, you need to enter all the information in a Device Description file (.xsidevice). The .xsidevice file uses the following XML tag structure:
<?xml version="1.0"?> <Device> <FileVersion>...</FileVersion> <DeviceName>...</DeviceName> <DeviceType>...</DeviceType> <DefaultPresetFilename>...</DefaultPresetFilename> <PluginFilename>...</PluginFilename> <SupportMultiInstance>...</SupportMultiInstance> <OtherInfo>...</OtherInfo> <OptionsPreset>...</OptionsPreset> <Description> <![CDATA[ ... ]]> </Description> <Channel> <ChannelName>...</ChannelName> <ChannelDescription> <![CDATA[ ... ]]> </ChannelDescription> <ChannelID>...</ChannelID> <ChannelDirectionType>...</ChannelDirectionType> <ChannelType>...</ChannelType> <ChannelMin>...</ChannelMin> <ChannelMax>...</ChannelMax> <SaveKeyOnSameValue>...</SaveKeyOnSameValue> </Channel> <Channel> ... </Channel> ... </Device>
Softimage uses these tags to build a list of available device drivers that users can access through the DeviceManager window.
XML device description tags reference
The following table lists each XML tag for devices and how to use it.
XML channel description tags reference
The following table lists each XML tag for channels and how to use it.
Validating XML device description files
When you launch Softimage, it reads each XML device description file and checks to make sure it is valid. If all .xsidevice files are valid, when you click on the Add button from the DeviceManager, the Select a Device Driver dialog box lists each driver.
However, if one or more of your .xsidevice files is not valid, as soon as you activate the DeviceManager a message identifying the problem with the file appears in the history log of the Script Editor window. For example, if you forgot to use a closing tag, this message appears:
'ERROR : "2000 - Error Parsing the DeviceInfo: mismatched tag at line ** col *'"
If you leave out the type of the device (no <DeviceType> set of tags), this message appears:
'ERROR : "2000 - Error parsing the Device [device_name], File: [$factory]\Data\Devices\[filename].xsidevice 'Error parsing the device: '- Device plugin filename is empty '"
To validate XML device description files outside Softimage
To verify whether or not your .xsidevice file is valid, you can use the deviceparser tool:
Open a command prompt and navigate to the bin directory of your installation folder (for example, C:\Softimage\Softimage_2012\Application\bin).
If your file is valid, this message appears followed by a summary of the information for the device and all valid channels:
Parsing device desription file: [$factory]\Data\Devices\[filename].xsidevice -- Succeeded
If your file is not valid, a message similar to this appears:
Parsing device desription file: [$factory]\Data\Devices\[filename].xsidevice Error Parsing the DeviceInfo: mismatched tag at line ** col *