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