Hi,
The bottom line is that I can read the movements but all of the buttons register as button #1 when pressed, and have not been able to synchronize any GUI functions.
I have been adding the SpacePilot to an application as a simple 3D joystick controller to control a cursor and to use the function buttons. In order to get windows messages, I had to grab the device exclusively with SiGrabDevice(), apparently because the DirectX window is above the application window pointed to by GetSafeHwd(). This gave me a response to movement and button events, but where the movement data is accurate, the buttons all register as button number 1 being pressed or released. I used the MFC code example as a template and the MFC example works with the same GUI loaded into the controller.
The combination of DirectX and MFC ActiveX have caused problems with other controllers and devices in the past, and since I'm an engineer and not a professional programmer I often need help seeing the obvious.
I would appreciate any suggestions or special concerns for this problem or any other experiences with this application combination.
Bruce
CODE:
bool CCGCIAPPCtrl::initSpacePilot() // initialize space pilot controller
{
SiOpenData Si_oData; // si open data structure
if( SiInitialize() != SPW_NO_ERROR ) // initialize the 3dxware input library
{
MessageBox( (LPCTSTR) "SpacePilot DLL Load Failure", 0, 0);
b_SpacePilotPresent = false;
return false;
}
SiOpenWinInit( &Si_oData, GetSafeHwnd() ); // initialize windows specific data
if(( m_SpacePilotHdl = SiOpen("CGCI", SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &Si_oData)) == NULL) // open data and get device handle
{
SiTerminate();
MessageBox( (LPCTSTR) "SpacePilot Open Failed", 0, 0);
b_SpacePilotPresent = false;
return false;
}
else b_SpacePilotPresent = true;
SiGrabDevice(m_SpacePilotHdl, SPW_TRUE); // exclusively use the spacepilot with this application
SiSetUiMode(&m_SpacePilotHdl, SI_UI_ALL_CONTROLS); // bring up the application GUI
return true;
}
LONG CCGCIAPPCtrl::On3DxWare( WPARAM wParam, LPARAM lParam ) // SpacePilot message call
{
SiSpwEvent Si_event; // event structure
SiGetEventData Si_eData; // event data structure
// Si_TestString = "event happened";
int num; // number of button pressed
SiGetEventWinInit( &Si_eData, WM_3DXWARE, wParam, lParam ); // decode 3dxware event
if( SiGetEvent(m_SpacePilotHdl, 0, &Si_eData, &Si_event) == SI_IS_EVENT )
{
switch (Si_event.type)
{
case SI_MOTION_EVENT:
SpacePilotDirection.x = (float) Si_event.u.spwData.mData[SI_TX] / 1000.0f;
SpacePilotDirection.y = (float) Si_event.u.spwData.mData[SI_TZ] / 1000.0f;
SpacePilotDirection.z = (float) Si_event.u.spwData.mData[SI_TY] / 1000.0f;
SpacePilotRotation.x = (float) Si_event.u.spwData.mData[SI_RX] / 3000.0f;
SpacePilotRotation.y = (float) Si_event.u.spwData.mData[SI_RZ] / 3000.0f;
SpacePilotRotation.z = (float) Si_event.u.spwData.mData[SI_RY] / 3000.0f;
// Si_TestString = "";
InvalidateControl();
break;
case SI_ZERO_EVENT:
break;
case SI_BUTTON_EVENT:
if( num = SiButtonPressed(&Si_event) != SI_NO_BUTTON )
{
Si_TestString.Format( _T("Button %d Pressed"), num);
}
if( num = SiButtonReleased(&Si_event) != SI_NO_BUTTON )
{
Si_TestString.Format( _T("Button %d Released"), num);
}
InvalidateControl();
break;
case SI_SYNC_EVENT:
SiSyncSetButtonName( m_SpacePilotHdl, 4, L"Headlight" );
break;
default:
break;
}
}
return (TRUE);
}
Compatibility with MFC ActiveX w/DirectX
Moderator: Moderators
-
- Posts: 2
- Joined: Tue Feb 20, 2007 3:08 pm
- Location: California
Hi Bruce,
You are correct, you need to use SiGrabDevice because of the windows layering issue.
You're getting a 1 for num because of C operator precedence. The expression isn't being evaluated the way you think it is. You need some more parens. Change the statements as such:
if ( (num= SiButtonPressed (&Si_event) ) != SI_NO_BUTTON)
Or better yet (I'm not sure about that SI_NO_BUTTON return value):
/* Look for Button Presses */
switch( num = SiButtonPressed ( &Si_Event ) )
{
case 1: ...
case 2:
...
}
You are correct, you need to use SiGrabDevice because of the windows layering issue.
You're getting a 1 for num because of C operator precedence. The expression isn't being evaluated the way you think it is. You need some more parens. Change the statements as such:
if ( (num= SiButtonPressed (&Si_event) ) != SI_NO_BUTTON)
Or better yet (I'm not sure about that SI_NO_BUTTON return value):
/* Look for Button Presses */
switch( num = SiButtonPressed ( &Si_Event ) )
{
case 1: ...
case 2:
...
}
-
- Posts: 2
- Joined: Tue Feb 20, 2007 3:08 pm
- Location: California
Thank You, that cured the buttons. My dumb mistake.
I've only started the menu synchronization, and it's clearly not as simple as setting
SiSyncSetInfoLine(m_SpacePilotHdl, -1, L"CGCI");
SiSyncSetButtonName( m_SpacePilotHdl, 1, L"MOVEMENT MENU");
SiSyncSetButtonName( m_SpacePilotHdl, 2, L"Zoom In");
SiSyncSetButtonName( m_SpacePilotHdl, 3, L"Zoom Out");
SiSyncSetButtonName( m_SpacePilotHdl, 4, L"Headlight" );
SiSyncSetButtonName( m_SpacePilotHdl, 5, L"Rotation ON" );
SiSyncSetButtonName( m_SpacePilotHdl, 6, L"Movement ON" );
these lines in the code, either in the SI_SYNC_EVENT or initialization. I will go through all of the synchronization steps in the documentation. Ideally I would like to dynamically change the titles for different menus, but keep all of the functions as "Button #". Are there any special considerations in the synchronization of the menu titles when working under SiGrabDevice in a window that is under the DirectX panel?
I've only started the menu synchronization, and it's clearly not as simple as setting
SiSyncSetInfoLine(m_SpacePilotHdl, -1, L"CGCI");
SiSyncSetButtonName( m_SpacePilotHdl, 1, L"MOVEMENT MENU");
SiSyncSetButtonName( m_SpacePilotHdl, 2, L"Zoom In");
SiSyncSetButtonName( m_SpacePilotHdl, 3, L"Zoom Out");
SiSyncSetButtonName( m_SpacePilotHdl, 4, L"Headlight" );
SiSyncSetButtonName( m_SpacePilotHdl, 5, L"Rotation ON" );
SiSyncSetButtonName( m_SpacePilotHdl, 6, L"Movement ON" );
these lines in the code, either in the SI_SYNC_EVENT or initialization. I will go through all of the synchronization steps in the documentation. Ideally I would like to dynamically change the titles for different menus, but keep all of the functions as "Button #". Are there any special considerations in the synchronization of the menu titles when working under SiGrabDevice in a window that is under the DirectX panel?
Hi Bruce,
There are two things you must do for synchronization to work.
1) Make sure the config file you are using has APP_CONTROLS_BUTTONS = TRUE. If you don't, the driver will ignore all attempts to sync. Turning on the log file will log everything that is happening in the syncing process.
2) Set all the buttons to "pass thru", either in the config file (set to Button 1, Button 2, Button 3, etc.) or use the Synch API to set them to pass thru SiSyncSetButtonAssignment(..., 0).
Jim
3Dx Software Development
There are two things you must do for synchronization to work.
1) Make sure the config file you are using has APP_CONTROLS_BUTTONS = TRUE. If you don't, the driver will ignore all attempts to sync. Turning on the log file will log everything that is happening in the syncing process.
2) Set all the buttons to "pass thru", either in the config file (set to Button 1, Button 2, Button 3, etc.) or use the Synch API to set them to pass thru SiSyncSetButtonAssignment(..., 0).
Jim
3Dx Software Development