1 /*
2 The zlib/libpng License
3
4 Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
5
6 This software is provided 'as-is', without any express or implied warranty. In no event will
7 the authors be held liable for any damages arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose, including commercial
10 applications, and to alter it and redistribute it freely, subject to the following
11 restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not claim that
14 you wrote the original software. If you use this software in a product,
15 an acknowledgment in the product documentation would be appreciated but is
16 not required.
17
18 2. Altered source versions must be plainly marked as such, and must not be
19 misrepresented as being the original software.
20
21 3. This notice may not be removed or altered from any source distribution.
22 */
23 #include "Win32/Win32Mouse.h"
24 #include "Win32/Win32InputManager.h"
25 #include "OISException.h"
26 #include "OISEvents.h"
27
28 using namespace OIS;
29
30 //--------------------------------------------------------------------------------------------------//
Win32Mouse(InputManager * creator,IDirectInput8 * pDI,bool buffered,DWORD coopSettings)31 Win32Mouse::Win32Mouse( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings )
32 : Mouse(creator->inputSystemName(), buffered, 0, creator)
33 {
34 mMouse = 0;
35 mDirectInput = pDI;
36 coopSetting = coopSettings;
37 mHwnd = 0;
38
39 static_cast<Win32InputManager*>(mCreator)->_setMouseUsed(true);
40 }
41
42 //--------------------------------------------------------------------------------------------------//
_initialize()43 void Win32Mouse::_initialize()
44 {
45 DIPROPDWORD dipdw;
46
47 //Clear old state
48 mState.clear();
49
50 dipdw.diph.dwSize = sizeof(DIPROPDWORD);
51 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
52 dipdw.diph.dwObj = 0;
53 dipdw.diph.dwHow = DIPH_DEVICE;
54 dipdw.dwData = MOUSE_DX_BUFFERSIZE;
55
56 if( FAILED(mDirectInput->CreateDevice(GUID_SysMouse, &mMouse, NULL)) )
57 OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to create device" );
58
59 if( FAILED(mMouse->SetDataFormat(&c_dfDIMouse2)) )
60 OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set format" );
61
62 mHwnd = ((Win32InputManager*)mCreator)->getWindowHandle();
63
64 if( FAILED(mMouse->SetCooperativeLevel(mHwnd, coopSetting)) )
65 OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set coop level" );
66
67 if( FAILED(mMouse->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph )) )
68 OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set property" );
69
70 HRESULT hr = mMouse->Acquire();
71 if (FAILED(hr) && hr != DIERR_OTHERAPPHASPRIO)
72 OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to aquire mouse!" );
73 }
74
75 //--------------------------------------------------------------------------------------------------//
~Win32Mouse()76 Win32Mouse::~Win32Mouse()
77 {
78 if (mMouse)
79 {
80 mMouse->Unacquire();
81 mMouse->Release();
82 mMouse = 0;
83 }
84
85 static_cast<Win32InputManager*>(mCreator)->_setMouseUsed(false);
86 }
87
88 //--------------------------------------------------------------------------------------------------//
capture()89 void Win32Mouse::capture()
90 {
91 //Clear old relative values
92 mState.X.rel = mState.Y.rel = mState.Z.rel = 0;
93
94 DIDEVICEOBJECTDATA diBuff[MOUSE_DX_BUFFERSIZE];
95 DWORD entries = MOUSE_DX_BUFFERSIZE;
96
97 HRESULT hr = mMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
98 if( hr != DI_OK )
99 {
100 hr = mMouse->Acquire();
101 while( hr == DIERR_INPUTLOST )
102 hr = mMouse->Acquire();
103
104 hr = mMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
105
106 //Perhaps the user just tabbed away, and coop settings
107 //are nonexclusive..so just ignore
108 if( FAILED(hr) )
109 return;
110 }
111
112 bool axesMoved = false;
113 //Accumulate all axis movements for one axesMove message..
114 //Buttons are fired off as they are found
115 for(unsigned int i = 0; i < entries; ++i )
116 {
117 switch( diBuff[i].dwOfs )
118 {
119 case DIMOFS_BUTTON0:
120 if(!_doMouseClick(0, diBuff[i])) return;
121 break;
122 case DIMOFS_BUTTON1:
123 if(!_doMouseClick(1, diBuff[i])) return;
124 break;
125 case DIMOFS_BUTTON2:
126 if(!_doMouseClick(2, diBuff[i])) return;
127 break;
128 case DIMOFS_BUTTON3:
129 if(!_doMouseClick(3, diBuff[i])) return;
130 break;
131 case DIMOFS_BUTTON4:
132 if(!_doMouseClick(4, diBuff[i])) return;
133 break;
134 case DIMOFS_BUTTON5:
135 if(!_doMouseClick(5, diBuff[i])) return;
136 break;
137 case DIMOFS_BUTTON6:
138 if(!_doMouseClick(6, diBuff[i])) return;
139 break;
140 case DIMOFS_BUTTON7:
141 if(!_doMouseClick(7, diBuff[i])) return;
142 break;
143 case DIMOFS_X:
144 mState.X.rel += diBuff[i].dwData;
145 axesMoved = true;
146 break;
147 case DIMOFS_Y:
148 mState.Y.rel += diBuff[i].dwData;
149 axesMoved = true;
150 break;
151 case DIMOFS_Z:
152 mState.Z.rel += diBuff[i].dwData;
153 axesMoved = true;
154 break;
155 default: break;
156 } //end switch
157 }//end for
158
159 if( axesMoved )
160 {
161 if( coopSetting & DISCL_NONEXCLUSIVE )
162 {
163 //DirectInput provides us with meaningless values, so correct that
164 POINT point;
165 GetCursorPos(&point);
166 ScreenToClient(mHwnd, &point);
167 mState.X.abs = point.x;
168 mState.Y.abs = point.y;
169 }
170 else
171 {
172 mState.X.abs += mState.X.rel;
173 mState.Y.abs += mState.Y.rel;
174 }
175 mState.Z.abs += mState.Z.rel;
176
177 //Clip values to window
178 if( mState.X.abs < 0 )
179 mState.X.abs = 0;
180 else if( mState.X.abs > mState.width )
181 mState.X.abs = mState.width;
182 if( mState.Y.abs < 0 )
183 mState.Y.abs = 0;
184 else if( mState.Y.abs > mState.height )
185 mState.Y.abs = mState.height;
186
187 //Do the move
188 if( mListener && mBuffered )
189 mListener->mouseMoved( MouseEvent( this, mState ) );
190 }
191 }
192
193 //--------------------------------------------------------------------------------------------------//
_doMouseClick(int mouseButton,DIDEVICEOBJECTDATA & di)194 bool Win32Mouse::_doMouseClick( int mouseButton, DIDEVICEOBJECTDATA& di )
195 {
196 if( di.dwData & 0x80 )
197 {
198 mState.buttons |= 1 << mouseButton; //turn the bit flag on
199 if( mListener && mBuffered )
200 return mListener->mousePressed( MouseEvent( this, mState ), (MouseButtonID)mouseButton );
201 }
202 else
203 {
204 mState.buttons &= ~(1 << mouseButton); //turn the bit flag off
205 if( mListener && mBuffered )
206 return mListener->mouseReleased( MouseEvent( this, mState ), (MouseButtonID)mouseButton );
207 }
208
209 return true;
210 }
211
212 //--------------------------------------------------------------------------------------------------//
setBuffered(bool buffered)213 void Win32Mouse::setBuffered(bool buffered)
214 {
215 mBuffered = buffered;
216 }
217