Skip to content

Commit

Permalink
Cleaned up DirectInput module and added apidoc
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed May 3, 2012
1 parent 13aea05 commit fad852e
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 31 deletions.
40 changes: 37 additions & 3 deletions doomsday/engine/win32/include/directinput.h
Expand Up @@ -3,26 +3,60 @@

#define WIN32_LEAN_AND_MEAN
#define DIRECTINPUT_VERSION 0x0800
#define _WIN32_WINNT 0x0501

#include <windows.h>
#include <dinput.h>
#include <assert.h>

#define I_SAFE_RELEASE(d) { if(d) { IDirectInputDevice_Release(d); (d) = NULL; } }
#define I_SAFE_RELEASE2(d) { if(d) { IDirectInputDevice2_Release(d); (d) = NULL; } }
#define I_SAFE_RELEASE(d) { if(d) { (d)->Release(); (d) = NULL; } }

#ifdef __cplusplus
extern "C" {
#endif

/**
* Attempt to initialize an application-global interface to DirectInput. First
* the version 8 interface (if available on the host system) and if unsuccessful,
* then the older version 3 interface.
*
* @important The caller must ensure that COM has been initialized else this
* will fail and false will be returned.
*
* @return @c true if an interface was initialized successfully.
*/
int DirectInput_Init(void);

/**
* Shutdown the open DirectInput interface if initialized.
*/
void DirectInput_Shutdown(void);

LPDIRECTINPUT8 DirectInput_Instance();
/**
* Retrieve a handle to the version 8 interface.
* @return Interface instance handle or @c NULL if not initialized.
*/
LPDIRECTINPUT8 DirectInput_IVersion8();

/**
* Retrieve a handle to the version 3 interface.
* @return Interface instance handle or @c NULL if not initialized.
*/
LPDIRECTINPUT DirectInput_IVersion3();

/**
* Releases and then destroys a DirectInput device.
* @param dev Address of the device instance to be destroyed. Can be @c NULL.
*/
void DirectInput_KillDevice(LPDIRECTINPUTDEVICE8* dev);

/**
* Retrieve a plain text explanation of a DirectInput error code suitable for
* printing to the error log/displaying to the user.
*
* @param hr DirectInput Error code to be translated.
* @return Plain text explanation. Always returns a valid cstring.
*/
const char* DirectInput_ErrorMsg(HRESULT hr);

#ifdef __cplusplus
Expand Down
19 changes: 10 additions & 9 deletions doomsday/engine/win32/src/directinput.cpp
Expand Up @@ -43,14 +43,14 @@ int DirectInput_Init(void)

if(dInput || dInput3) return true;

// We'll create the DirectInput object.
// Create the DirectInput interface instance. Try version 8 first.
if(FAILED(hr = CoCreateInstance(CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
IID_IDirectInput8, (LPVOID*)&dInput)) ||
FAILED(hr = dInput->Initialize(app.hInstance, DIRECTINPUT_VERSION)))
{
Con_Message("DirectInput 8 init failed (0x%x).\n", hr);

// Try DInput3 instead.
// Try the older version 3 interface instead.
// I'm not sure if this works correctly.
if(FAILED(hr = CoCreateInstance(CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER,
IID_IDirectInput2W, (LPVOID*)&dInput3)) ||
Expand All @@ -74,9 +74,6 @@ int DirectInput_Init(void)

void DirectInput_Shutdown(void)
{
if(!dInput && !dInput3) return;

// Release DirectInput.
if(dInput)
{
IDirectInput_Release(dInput);
Expand All @@ -89,14 +86,18 @@ void DirectInput_Shutdown(void)
}
}

LPDIRECTINPUT8 DirectInput_Instance()
LPDIRECTINPUT8 DirectInput_IVersion8()
{
return dInput;
}

LPDIRECTINPUT DirectInput_IVersion3()
{
assert(dInput != 0 || dInput3 != 0);
return dInput? dInput : (LPDIRECTINPUT8)dInput3;
return dInput3;
}

void DirectInput_KillDevice(LPDIRECTINPUTDEVICE8* dev)
{
if(*dev) IDirectInputDevice8_Unacquire(*dev);
if(*dev) (*dev)->Unacquire();
I_SAFE_RELEASE(*dev);
}
29 changes: 17 additions & 12 deletions doomsday/engine/win32/src/joystick_win32.cpp
Expand Up @@ -77,11 +77,16 @@ boolean Joystick_Init(void)
HWND hWnd = (HWND) Window_NativeHandle(Window_Main());
if(!hWnd)
{
Con_Error("Joystick_Init: Main window not available, cannot init joystick.");
Con_Error("Joystick_Init: Main window not available, cannot continue.");
return false;
}

LPDIRECTINPUT8 dInput = DirectInput_Instance();
LPDIRECTINPUT8 dInput = DirectInput_IVersion8();
if(!dInput)
{
Con_Message("Joystick_Init: DirectInput version 8 interface not available, cannot continue.\n");
return false;
}

// ddi will contain info for the joystick device.
DIDEVICEINSTANCE ddi;
Expand All @@ -99,35 +104,35 @@ boolean Joystick_Init(void)
if(!firstJoystick.dwSize)
return false; // Not found.

Con_Message("I_InitJoystick: joydevice = %i, out of range.\n", joyDevice);
Con_Message("Joystick_Init: joydevice = %i, out of range.\n", joyDevice);
// Use the first joystick that was found.
memcpy(&ddi, &firstJoystick, sizeof(ddi));
}

// Show some info.
Con_Message("I_InitJoystick: %s\n", ddi.tszProductName);
Con_Message("Joystick_Init: %s\n", ddi.tszProductName);

// Create the joystick device.
HRESULT hr = dInput->CreateDevice(ddi.guidInstance, &didJoy, 0);
if(FAILED(hr))
{
Con_Message("I_InitJoystick: Failed to create device (0x%x).\n", hr);
Con_Message("Joystick_Init: Failed to create device (0x%x).\n", hr);
return false;
}

// Set data format.
hr = didJoy->SetDataFormat(&c_dfDIJoystick);
if(FAILED(hr))
{
Con_Message("I_InitJoystick: Failed to set data format (0x%x).\n", hr);
Con_Message("Joystick_Init: Failed to set data format (0x%x).\n", hr);
goto kill_joy;
}

// Set behavior.
hr = didJoy->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
if(FAILED(hr))
{
Con_Message("I_InitJoystick: Failed to set co-op level (0x%x: %s).\n",
Con_Message("Joystick_Init: Failed to set co-op level (0x%x: %s).\n",
hr, DirectInput_ErrorMsg(hr));
goto kill_joy;
}
Expand All @@ -139,24 +144,24 @@ boolean Joystick_Init(void)
if(FAILED(hr))
{
if(verbose)
Con_Message("I_InitJoystick: Failed to set %s "
"range (0x%x: %s).\n", axisName[i], hr, DirectInput_ErrorMsg(hr));
Con_Message("Joystick_Init: Failed to set axis '%s' range (0x%x: %s).\n",
axisName[i], hr, DirectInput_ErrorMsg(hr));
}
}

// Set no dead zone.
// Set no dead zone. We'll handle this ourselves thanks...
hr = didJoy->SetProperty(DIPROP_DEADZONE, DIPropDWord(DIPH_DEVICE));
if(FAILED(hr))
{
Con_Message("I_InitJoystick: Failed to set dead zone (0x%x: %s).\n",
Con_Message("Joystick_Init: Failed to set dead zone (0x%x: %s).\n",
hr, DirectInput_ErrorMsg(hr));
}

// Set absolute mode.
hr = didJoy->SetProperty(DIPROP_AXISMODE, DIPropDWord(DIPH_DEVICE, 0, DIPROPAXISMODE_ABS));
if(FAILED(hr))
{
Con_Message("I_InitJoystick: Failed to set absolute axis mode (0x%x: %s).\n",
Con_Message("Joystick_Init: Failed to set absolute axis mode (0x%x: %s).\n",
hr, DirectInput_ErrorMsg(hr));
}

Expand Down
26 changes: 19 additions & 7 deletions doomsday/engine/win32/src/mouse_win32.cpp
Expand Up @@ -36,35 +36,47 @@ static int Mouse_Win32_Init(void)
{
if(ArgCheck("-nomouse") || novideo) return false;

// We'll need a window handle for this.
HWND hWnd = (HWND) Window_NativeHandle(Window_Main());
if(!hWnd)
{
Con_Error("I_InitMouse: Main window not available, cannot init mouse.");
Con_Error("Mouse_Init: Main window not available, cannot init mouse.");
return false;
}

LPDIRECTINPUT8 dInput = DirectInput_Instance();
HRESULT hr = -1;
// Prefer the newer version 8 interface if available.
if(LPDIRECTINPUT8 dInput = DirectInput_IVersion8())
{
hr = dInput->CreateDevice(GUID_SysMouse, &didMouse, 0);
}
else if(LPDIRECTINPUT dInput = DirectInput_IVersion3())
{
hr = dInput->CreateDevice(GUID_SysMouse, (LPDIRECTINPUTDEVICE*) &didMouse, 0);
}

HRESULT hr = dInput->CreateDevice(GUID_SysMouse, &didMouse, 0);
if(FAILED(hr))
{
Con_Message("I_InitMouse: Failed to create device (0x%x).\n", hr);
Con_Message("Mouse_Init: Failed to create device (0x%x: %s).\n",
hr, DirectInput_ErrorMsg(hr));
return false;
}

// Set data format.
hr = didMouse->SetDataFormat(&c_dfDIMouse2);
if(FAILED(hr))
{
Con_Message("I_InitMouse: Failed to set data format (0x%x).\n", hr);
Con_Message("Mouse_Init: Failed to set data format (0x%x: %s).\n",
hr, DirectInput_ErrorMsg(hr));
goto kill_mouse;
}

// Set behavior.
hr = didMouse->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE);
hr = didMouse->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
if(FAILED(hr))
{
Con_Message("I_InitMouse: Failed to set co-op level (0x%x).\n", hr);
Con_Message("Mouse_Init: Failed to set co-op level (0x%x: %s).\n",
hr, DirectInput_ErrorMsg(hr));
goto kill_mouse;
}

Expand Down

0 comments on commit fad852e

Please sign in to comment.