From 629c2322f48458d4775020d37eae9b99f5869b8b Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 9 Jan 2003 22:33:37 +0000 Subject: [PATCH] new window code --- panda/src/dxgsg8/dxInput8.cxx | 276 ++++++++++++++++++++++++++++++++++ panda/src/dxgsg8/dxInput8.h | 45 ++++++ 2 files changed, 321 insertions(+) create mode 100644 panda/src/dxgsg8/dxInput8.cxx create mode 100644 panda/src/dxgsg8/dxInput8.h diff --git a/panda/src/dxgsg8/dxInput8.cxx b/panda/src/dxgsg8/dxInput8.cxx new file mode 100644 index 0000000000..a6d4ac5b0d --- /dev/null +++ b/panda/src/dxgsg8/dxInput8.cxx @@ -0,0 +1,276 @@ +// Filename: dxInput8.cxx +// Created by: angelina jolie (07Oct99) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "config_wdxdisplay8.h" +#include + +#define AXIS_RESOLUTION 2000 // use this many levels of resolution by default (could be more if needed and device supported it) +#define AXIS_RANGE_CENTERED // if defined, axis range is centered on 0, instead of starting on 0 + +BOOL CALLBACK EnumGameCtrlsCallback( const DIDEVICEINSTANCE* pdidInstance, + VOID* pContext ) { + DI_DeviceInfos *pDevInfos = (DI_DeviceInfos *)pContext; + + (*pDevInfos).push_back(*pdidInstance); + + if(wdxdisplay_cat.is_debug()) + wdxdisplay_cat.debug() << "Found DevType 0x" << (void*)pdidInstance->dwDevType << ": " << pdidInstance->tszInstanceName << ": " << pdidInstance->tszProductName <Unacquire(); + SAFE_RELEASE(_DeviceList[i]); + } + + // bugbug: need to handle this + // if(_JoystickPollTimer!=NULL) + // KillTimer(...) + + SAFE_RELEASE(_pDInput8); + if(_hDInputDLL) { + FreeLibrary(_hDInputDLL); + _hDInputDLL=NULL; + } +} + +bool DInput8Info::InitDirectInput(void) { + HRESULT hr; + + // assumes dx8 exists + // use dynamic load so non-dinput programs dont have to load dinput + #define DLLNAME "dinput8.dll" + #define DINPUTCREATE "DirectInput8Create" + + HINSTANCE _hDInputDLL = LoadLibrary(DLLNAME); + if(_hDInputDLL == 0) { + wdxdisplay_cat.fatal() << "LoadLibrary(" << DLLNAME <<") failed!, error=" << GetLastError() << endl; + exit(1); + } + + typedef HRESULT (WINAPI * LPDIRECTINPUT8CREATE)(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter); + LPDIRECTINPUT8CREATE pDInputCreate8; + + pDInputCreate8 = (LPDIRECTINPUT8CREATE) GetProcAddress(_hDInputDLL,DINPUTCREATE); + if(pDInputCreate8 == NULL) { + wdxdisplay_cat.fatal() << "GetProcAddr failed for " << DINPUTCREATE << endl; + exit(1); + } + + // Register with the DirectInput subsystem and get a pointer + // to a IDirectInput interface we can use. + // Create a DInput object + if( FAILED( hr = (*pDInputCreate8)(GetModuleHandle(NULL), DIRECTINPUT_VERSION, + IID_IDirectInput8, (VOID**)&_pDInput8, NULL ) ) ) { + wdxdisplay_cat.error() << DINPUTCREATE << "failed" << D3DERRORSTRING(hr); + return false; + } + + // enum all the joysticks,etc (but not keybd/mouse) + if( FAILED( hr = _pDInput8->EnumDevices(DI8DEVCLASS_GAMECTRL, + EnumGameCtrlsCallback, + (LPVOID)&_DevInfos, DIEDFL_ATTACHEDONLY ) ) ) { + wdxdisplay_cat.error() << "EnumDevices failed" << D3DERRORSTRING(hr); + return false; + } + + return true; +} + +bool DInput8Info::CreateJoystickOrPad(HWND hWnd) { + bool bFoundDev = false; + UINT devnum=0; + char *errstr=NULL; + + // look through the list for the first joystick or gamepad + for(;devnum<_DevInfos.size();devnum++) { + DWORD devType = GET_DIDEVICE_TYPE(_DevInfos[devnum].dwDevType); + if((devType==DI8DEVTYPE_GAMEPAD) ||(devType==DI8DEVTYPE_JOYSTICK)) { + bFoundDev=true; + break; + } + } + + if(!bFoundDev) { + wdxdisplay_cat.error() << "Cant find an attached Joystick or GamePad!\n"; + return false; + } + + LPDIRECTINPUTDEVICE8 pJoyDevice; + + // Obtain an interface to the enumerated joystick. + HRESULT hr = _pDInput8->CreateDevice(_DevInfos[devnum].guidInstance, &pJoyDevice, NULL ); + if(FAILED(hr)) { + errstr="CreateDevice"; + goto handle_error; + } + + assert(pJoyDevice!=NULL); + _DeviceList.push_back(pJoyDevice); + + // Set the data format to "simple joystick" - a predefined data format + // + // A data format specifies which controls on a device we are interested in, + // and how they should be reported. This tells DInput that we will be + // passing a DIJOYSTATE2 structure to IDirectInputDevice::GetDeviceState(). + hr = pJoyDevice->SetDataFormat(&c_dfDIJoystick2); + if(FAILED(hr)) { + errstr="SetDataFormat"; + goto handle_error; + } + + // must be called AFTER SetDataFormat to get all the proper flags + DX_DECLARE_CLEAN(DIDEVCAPS, DIDevCaps); + hr = pJoyDevice->GetCapabilities(&DIDevCaps); + assert(SUCCEEDED(hr)); + + _DevCaps.push_back(DIDevCaps); + + if(wdxdisplay_cat.is_debug()) + wdxdisplay_cat.debug() << "Joy/Pad has " << DIDevCaps.dwAxes << " Axes, " << DIDevCaps.dwButtons << " Buttons, " << DIDevCaps.dwPOVs << " POVs" << endl; + + // Set the cooperative level to let DInput know how this device should + // interact with the system and with other DInput applications. + hr = pJoyDevice->SetCooperativeLevel( hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND); + if(FAILED(hr)) { + errstr="SetCooperativeLevel"; + goto handle_error; + } + + // set the min/max values property for discovered axes. + hr = pJoyDevice->EnumObjects(EnumObjectsCallbackJoystick, (LPVOID)pJoyDevice, DIDFT_AXIS); + if(FAILED(hr)) { + errstr="EnumObjects"; + goto handle_error; + } + + return true; + + handle_error: + wdxdisplay_cat.error() << errstr << " failed for (" << _DevInfos[devnum].tszInstanceName << ":" << _DevInfos[devnum].tszProductName << ")" << D3DERRORSTRING(hr); + return false; +} + +//----------------------------------------------------------------------------- +// Name: EnumObjectsCallback() +// Desc: Callback function for enumerating objects (axes, buttons, POVs) on a +// joystick. This function enables user interface elements for objects +// that are found to exist, and scales axes min/max values. +//----------------------------------------------------------------------------- +BOOL CALLBACK EnumObjectsCallbackJoystick( const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext ) { + + LPDIRECTINPUTDEVICE8 pJoyDevice = (LPDIRECTINPUTDEVICE8) pContext; + HRESULT hr; + + // For axes that are returned, set the DIPROP_RANGE property for the + // enumerated axis in order to scale min/max values. + if( pdidoi->dwType & DIDFT_AXIS ) { + DIPROPRANGE diprg; + diprg.diph.dwSize = sizeof(DIPROPRANGE); + diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = pdidoi->dwType; // Specify the enumerated axis + + #ifdef AXIS_RANGE_CENTERED + diprg.lMin = -AXIS_RESOLUTION/2; + diprg.lMax = +AXIS_RESOLUTION/2; + #else + diprg.lMin = 0; + diprg.lMax = +AXIS_RESOLUTION; + #endif + + // Set the range for the axis + hr = pJoyDevice->SetProperty( DIPROP_RANGE, &diprg.diph); + if(FAILED(hr)) { + wdxdisplay_cat.error() << "SetProperty on axis failed" << D3DERRORSTRING(hr); + return DIENUM_STOP; + } + } + + return DIENUM_CONTINUE; +} + +bool DInput8Info::ReadJoystick(int devnum, DIJOYSTATE2 &js) { + LPDIRECTINPUTDEVICE8 pJoystick = _DeviceList[devnum]; + assert(pJoystick!=NULL); + HRESULT hr; + char *errstr; + + // Poll the device to read the current state + + hr = pJoystick->Poll(); + + if( FAILED(hr) ) { + // DInput is telling us that the input stream has been + // interrupted. We aren't tracking any state between polls, so + // we don't have any special reset that needs to be done. We + // just re-acquire and try again. + + if((hr==DIERR_NOTACQUIRED)||(hr == DIERR_INPUTLOST)) { + hr = pJoystick->Acquire(); + + if(FAILED(hr)) { + if(wdxdisplay_cat.is_spam()) + wdxdisplay_cat.spam() << "Acquire failed" << D3DERRORSTRING(hr); + + // hr may be DIERR_OTHERAPPHASPRIO or other errors. This + // may occur when the app is minimized or in the process of + // switching, so just try again later + return false; + } + + hr = pJoystick->Poll(); + if(FAILED(hr)) { + // should never happen! + errstr = "Poll after successful Acquire failed"; + goto handle_error; + } + } else { + errstr = "Unknown Poll failure"; + goto handle_error; + } + } + + // should we make a vector of devstate dataformats to generalize this fn for all device types? + + // Get the input's device state + hr = pJoystick->GetDeviceState( sizeof(DIJOYSTATE2), &js); + if(FAILED(hr)) { + errstr = "GetDeviceState failed"; + goto handle_error; + } + + return true; + + handle_error: + wdxdisplay_cat.fatal() << errstr << D3DERRORSTRING(hr); + return false; +} + + diff --git a/panda/src/dxgsg8/dxInput8.h b/panda/src/dxgsg8/dxInput8.h new file mode 100644 index 0000000000..85b72eb15e --- /dev/null +++ b/panda/src/dxgsg8/dxInput8.h @@ -0,0 +1,45 @@ +// Filename: dxInput8.h +// Created by: blllyjo (07Oct99) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef DXINPUT8_H +#define DXINPUT8_H + +#define DIRECTINPUT_VERSION 0x800 +#include +typedef vector DI_DeviceInfos; +typedef vector DI_DeviceObjInfos; + +class DInput8Info { +public: + DInput8Info(void); + ~DInput8Info(void); + bool InitDirectInput(void); + bool CreateJoystickOrPad(HWND hWnd); + bool ReadJoystick(int devnum, DIJOYSTATE2 &js); + + HINSTANCE _hDInputDLL; + UINT_PTR _JoystickPollTimer; + LPDIRECTINPUT8 _pDInput8; + DI_DeviceInfos _DevInfos; + // arrays for all created devices. Should probably put these together in a struct, + // along with the data fmt info + vector _DeviceList; + vector _DevCaps; +}; + +#endif