summaryrefslogtreecommitdiffstats
path: root/src/joystick.cpp
blob: 41d9f56726eb5b30e12314a97a22d639408b823c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
// joystick.cpp

#define STRICT

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

#include "joystick.h"




// Global variables.

LPDIRECTINPUT7			g_pDI       = NULL;         
LPDIRECTINPUTDEVICE2	g_pJoystick = NULL;     
DIDEVCAPS				g_diDevCaps;





// Called once for each enumerated joystick. If we find one, create a
// device interface on it so we can play with it.

BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance,
                                     VOID* pContext )
{
    HRESULT hr;

    // Obtain an interface to the enumerated joystick.
    hr = g_pDI->CreateDeviceEx( pdidInstance->guidInstance, IID_IDirectInputDevice2,
		                        (VOID**)&g_pJoystick, NULL );

    // If it failed, then we can't use this joystick. (Maybe the user unplugged
    // it while we were in the middle of enumerating it.)
    if( FAILED(hr) ) 
        return DIENUM_CONTINUE;


    // Stop enumeration. Note: we're just taking the first joystick we get. You
    // could store all the enumerated joysticks and let the user pick.
    return DIENUM_STOP;
}


// Callback function for enumerating the axes on a joystick.

BOOL CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
                                VOID* pContext )
{
    DIPROPRANGE diprg; 
    diprg.diph.dwSize       = sizeof(DIPROPRANGE); 
    diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
    diprg.diph.dwHow        = DIPH_BYOFFSET; 
    diprg.diph.dwObj        = pdidoi->dwOfs; // Specify the enumerated axis
    diprg.lMin              = -1000; 
    diprg.lMax              = +1000; 
    
    // Set the range for the axis
    if( FAILED( g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) )
        return DIENUM_STOP;

    // Set the UI to reflect what axes the joystick supports
    switch( pdidoi->dwOfs )
    {
        case DIJOFS_X:
			OutputDebugString("EnumAxesCallback -x\n");
            break;
        case DIJOFS_Y:
			OutputDebugString("EnumAxesCallback -y\n");
            break;
        case DIJOFS_Z:
			OutputDebugString("EnumAxesCallback -z\n");
            break;
        case DIJOFS_RX:
			OutputDebugString("EnumAxesCallback -rx\n");
            break;
        case DIJOFS_RY:
			OutputDebugString("EnumAxesCallback -ry\n");
            break;
        case DIJOFS_RZ:
			OutputDebugString("EnumAxesCallback -rz\n");
            break;
        case DIJOFS_SLIDER(0):
			OutputDebugString("EnumAxesCallback -s0\n");
            break;
        case DIJOFS_SLIDER(1):
			OutputDebugString("EnumAxesCallback -s1\n");
            break;
    }

    return DIENUM_CONTINUE;
}


// Initialize the DirectInput variables.

BOOL InitDirectInput(HINSTANCE hInst, HWND hWnd)
{
    HRESULT hr;

    // Register with the DirectInput subsystem and get a pointer
    // to a IDirectInput interface we can use.
    hr = DirectInputCreateEx( hInst, DIRECTINPUT_VERSION,IID_IDirectInput7, (LPVOID*)&g_pDI, NULL );
    if( FAILED(hr) )  return FALSE;;

    // Look for a simple joystick we can use for this sample program.
    hr = g_pDI->EnumDevices( DIDEVTYPE_JOYSTICK, EnumJoysticksCallback,
                             NULL, DIEDFL_ATTACHEDONLY );
    if( FAILED(hr) )  return FALSE;

    // Make sure we got a joystick
    if( NULL == g_pJoystick )
    {
//?        MessageBox( NULL, "Joystick not found", "DInput Sample", 
//?                    MB_ICONERROR | MB_OK );
        return FALSE;
    }

    // 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 DIJOYSTATE structure to IDirectInputDevice::GetDeviceState().
    hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick );
    if( FAILED(hr) )  return FALSE;

    // Set the cooperative level to let DInput know how this device should
    // interact with the system and with other DInput applications.
    hr = g_pJoystick->SetCooperativeLevel( hWnd, DISCL_EXCLUSIVE|DISCL_FOREGROUND );
    if( FAILED(hr) )  return FALSE;

    // Determine how many axis the joystick has (so we don't error out setting
    // properties for unavailable axis)
    g_diDevCaps.dwSize = sizeof(DIDEVCAPS);
    hr = g_pJoystick->GetCapabilities(&g_diDevCaps);
    if( FAILED(hr) )  return FALSE;


    // Enumerate the axes of the joyctick and set the range of each axis. Note:
    // we could just use the defaults, but we're just trying to show an example
    // of enumerating device objects (axes, buttons, etc.).
    g_pJoystick->EnumObjects( EnumAxesCallback, (VOID*)g_pJoystick, DIDFT_AXIS );

    return TRUE;
}

// Acquire or unacquire the keyboard, depending on if the app is active
// Input device must be acquired before the GetDeviceState is called.

BOOL SetAcquire(BOOL bActive)
{
    if ( g_pJoystick )
    {
        if( bActive )  g_pJoystick->Acquire();
        else           g_pJoystick->Unacquire();
    }
    return TRUE;
}


// Get the input device's state and display it.

BOOL UpdateInputState( DIJOYSTATE &js )
{
    HRESULT     hr;

    if ( g_pJoystick ) 
    {
        do
        {
            // Poll the device to read the current state
            hr = g_pJoystick->Poll();
            if ( FAILED(hr) )  return FALSE;

            // Get the input's device state
            hr = g_pJoystick->GetDeviceState( sizeof(DIJOYSTATE), &js );

            if( hr == DIERR_INPUTLOST )
            {
                // 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.
                hr = g_pJoystick->Acquire();
                if ( FAILED(hr) )  return FALSE;
            }
        }
        while ( DIERR_INPUTLOST == hr );
        if ( FAILED(hr) )  return FALSE;
    } 
    return TRUE;
}


// Initialize the DirectInput variables.

BOOL FreeDirectInput()
{
    // Unacquire and release any DirectInputDevice objects.
    if( NULL != g_pJoystick ) 
    {
        // Unacquire the device one last time just in case 
        // the app tried to exit while the device is still acquired.
        g_pJoystick->Unacquire();
        g_pJoystick->Release();
        g_pJoystick = NULL;
    }


    // Release any DirectInput objects.
    if( g_pDI ) 
    {
        g_pDI->Release();
        g_pDI = NULL;
    }

    return TRUE;
}