211 lines
6.9 KiB
C++
211 lines
6.9 KiB
C++
|
/* OpenSceneGraph example, osgdirectinput.
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
* of this software and associated documentation files (the "Software"), to deal
|
||
|
* in the Software without restriction, including without limitation the rights
|
||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
* copies of the Software, and to permit persons to whom the Software is
|
||
|
* furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
|
* THE SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
#include <osgGA/EventQueue>
|
||
|
#include <iostream>
|
||
|
#include "DirectInputRegistry"
|
||
|
|
||
|
typedef std::pair<int, int> KeyValue;
|
||
|
typedef std::map<int, KeyValue> KeyMap;
|
||
|
KeyMap g_keyMap;
|
||
|
|
||
|
void buildKeyMap()
|
||
|
{
|
||
|
// TODO: finish the key map as you wish
|
||
|
g_keyMap[DIK_ESCAPE] = KeyValue(osgGA::GUIEventAdapter::KEY_Escape, 0);
|
||
|
g_keyMap[DIK_1] = KeyValue('1', 0);
|
||
|
g_keyMap[DIK_2] = KeyValue('2', 0);
|
||
|
g_keyMap[DIK_3] = KeyValue('3', 0);
|
||
|
g_keyMap[DIK_4] = KeyValue('4', 0);
|
||
|
g_keyMap[DIK_5] = KeyValue('5', 0);
|
||
|
g_keyMap[DIK_6] = KeyValue('6', 0);
|
||
|
g_keyMap[DIK_7] = KeyValue('7', 0);
|
||
|
g_keyMap[DIK_8] = KeyValue('8', 0);
|
||
|
g_keyMap[DIK_9] = KeyValue('9', 0);
|
||
|
g_keyMap[DIK_0] = KeyValue('0', 0);
|
||
|
g_keyMap[DIK_MINUS] = KeyValue('-', 0);
|
||
|
g_keyMap[DIK_EQUALS] = KeyValue('=', 0);
|
||
|
g_keyMap[DIK_BACK] = KeyValue(osgGA::GUIEventAdapter::KEY_BackSpace, 0);
|
||
|
g_keyMap[DIK_TAB] = KeyValue(osgGA::GUIEventAdapter::KEY_Tab, 0);
|
||
|
g_keyMap[DIK_SPACE] = KeyValue(osgGA::GUIEventAdapter::KEY_Space, 0);
|
||
|
}
|
||
|
|
||
|
bool DirectInputRegistry::initKeyboard( HWND handle )
|
||
|
{
|
||
|
if ( !_inputDevice ) return false;
|
||
|
|
||
|
HRESULT hr = _inputDevice->CreateDevice( GUID_SysKeyboard, &_keyboard, NULL );
|
||
|
if ( FAILED(hr) || _keyboard==NULL )
|
||
|
{
|
||
|
osg::notify(osg::WARN) << "Unable to create keyboard." << std::endl;
|
||
|
return false;
|
||
|
}
|
||
|
buildKeyMap();
|
||
|
return initImplementation( handle, _keyboard, &c_dfDIKeyboard );
|
||
|
}
|
||
|
|
||
|
bool DirectInputRegistry::initMouse( HWND handle )
|
||
|
{
|
||
|
if ( !_inputDevice ) return false;
|
||
|
|
||
|
HRESULT hr = _inputDevice->CreateDevice( GUID_SysMouse, &_mouse, NULL );
|
||
|
if ( FAILED(hr) || _mouse==NULL )
|
||
|
{
|
||
|
osg::notify(osg::WARN) << "Unable to create mouse." << std::endl;
|
||
|
return false;
|
||
|
}
|
||
|
return initImplementation( handle, _mouse, &c_dfDIMouse2 );
|
||
|
}
|
||
|
|
||
|
bool DirectInputRegistry::initJoystick( HWND handle )
|
||
|
{
|
||
|
if ( !_inputDevice ) return false;
|
||
|
|
||
|
HRESULT hr = _inputDevice->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback,
|
||
|
NULL, DIEDFL_ATTACHEDONLY );
|
||
|
if ( FAILED(hr) || _joystick==NULL )
|
||
|
{
|
||
|
osg::notify(osg::WARN) << "Unable to enumerate joysticks." << std::endl;
|
||
|
return false;
|
||
|
}
|
||
|
return initImplementation( handle, _joystick, &c_dfDIJoystick2 );
|
||
|
}
|
||
|
|
||
|
void DirectInputRegistry::updateState( osgGA::EventQueue* eventQueue )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
if ( !_supportDirectInput || !eventQueue ) return;
|
||
|
|
||
|
if ( _keyboard )
|
||
|
{
|
||
|
pollDevice( _keyboard );
|
||
|
|
||
|
char buffer[256] = {0};
|
||
|
hr = _keyboard->GetDeviceState( sizeof(buffer), &buffer );
|
||
|
if ( SUCCEEDED(hr) )
|
||
|
{
|
||
|
for ( KeyMap::iterator itr=g_keyMap.begin(); itr!=g_keyMap.end(); ++itr )
|
||
|
{
|
||
|
KeyValue& key = itr->second;
|
||
|
char value = buffer[itr->first];
|
||
|
if ( key.second==value ) continue;
|
||
|
|
||
|
key.second = value;
|
||
|
if ( value&0x80 )
|
||
|
eventQueue->keyPress( key.first );
|
||
|
else
|
||
|
eventQueue->keyRelease( key.first );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( _mouse )
|
||
|
{
|
||
|
pollDevice( _mouse );
|
||
|
|
||
|
DIMOUSESTATE2 mouseState;
|
||
|
hr = _mouse->GetDeviceState( sizeof(DIMOUSESTATE2), &mouseState );
|
||
|
|
||
|
// TODO: add mouse handlers
|
||
|
}
|
||
|
|
||
|
if ( _joystick )
|
||
|
{
|
||
|
pollDevice( _joystick );
|
||
|
|
||
|
osg::ref_ptr<JoystickEvent> event = new JoystickEvent;
|
||
|
hr = _joystick->GetDeviceState( sizeof(DIJOYSTATE2), &(event->_js) );
|
||
|
if ( SUCCEEDED(hr) ) eventQueue->userEvent( event.get() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DirectInputRegistry::DirectInputRegistry()
|
||
|
: _keyboard(0), _mouse(0), _joystick(0),
|
||
|
_supportDirectInput(true)
|
||
|
{
|
||
|
HRESULT hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION,
|
||
|
IID_IDirectInput8, (VOID**)&_inputDevice, NULL );
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
osg::notify(osg::WARN) << "Unable to create DirectInput object." << std::endl;
|
||
|
_supportDirectInput = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DirectInputRegistry::~DirectInputRegistry()
|
||
|
{
|
||
|
releaseDevice( _keyboard );
|
||
|
releaseDevice( _mouse );
|
||
|
releaseDevice( _joystick );
|
||
|
if ( _inputDevice ) _inputDevice->Release();
|
||
|
}
|
||
|
|
||
|
bool DirectInputRegistry::initImplementation( HWND handle, LPDIRECTINPUTDEVICE8 device, LPCDIDATAFORMAT format )
|
||
|
{
|
||
|
_supportDirectInput = true;
|
||
|
HRESULT hr = device->SetDataFormat( format );
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
osg::notify(osg::WARN) << "Unable to set device data format." << std::endl;
|
||
|
_supportDirectInput = false;
|
||
|
}
|
||
|
|
||
|
hr = device->SetCooperativeLevel( handle, DISCL_EXCLUSIVE|DISCL_FOREGROUND );
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
osg::notify(osg::WARN) << "Unable to attach device to window." << std::endl;
|
||
|
_supportDirectInput = false;
|
||
|
}
|
||
|
|
||
|
device->Acquire();
|
||
|
return _supportDirectInput;
|
||
|
}
|
||
|
|
||
|
void DirectInputRegistry::pollDevice( LPDIRECTINPUTDEVICE8 device )
|
||
|
{
|
||
|
HRESULT hr = device->Poll();
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
device->Acquire();
|
||
|
if ( hr==DIERR_INPUTLOST )
|
||
|
osg::notify(osg::WARN) << "Device lost." << std::endl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void DirectInputRegistry::releaseDevice( LPDIRECTINPUTDEVICE8 device )
|
||
|
{
|
||
|
if ( device )
|
||
|
{
|
||
|
device->Unacquire();
|
||
|
device->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL CALLBACK DirectInputRegistry::EnumJoysticksCallback( const DIDEVICEINSTANCE* didInstance, VOID* )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
LPDIRECTINPUT8 device = DirectInputRegistry::instance()->getDevice();
|
||
|
if ( device )
|
||
|
{
|
||
|
hr = device->CreateDevice( didInstance->guidInstance,
|
||
|
&(DirectInputRegistry::instance()->getJoyStick()), NULL );
|
||
|
}
|
||
|
if ( FAILED(hr) ) return DIENUM_CONTINUE;
|
||
|
return DIENUM_STOP;
|
||
|
}
|