PageRenderTime 55ms CodeModel.GetById 4ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 0ms

/src/ois/src/win32/extras/WiiMote/OISWiiMote.cpp

https://bitbucket.org/cabalistic/ogredeps/
C++ | 373 lines | 263 code | 54 blank | 56 comment | 80 complexity | 7511304a3ff9260994e650ffdf8aa3a2 MD5 | raw file
  1#include "OISConfig.h"
  2#ifdef OIS_WIN32_WIIMOTE_SUPPORT
  3/*
  4The zlib/libpng License
  5
  6Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
  7
  8This software is provided 'as-is', without any express or implied warranty. In no event will
  9the authors be held liable for any damages arising from the use of this software.
 10
 11Permission is granted to anyone to use this software for any purpose, including commercial
 12applications, and to alter it and redistribute it freely, subject to the following
 13restrictions:
 14
 15    1. The origin of this software must not be misrepresented; you must not claim that
 16		you wrote the original software. If you use this software in a product,
 17		an acknowledgment in the product documentation would be appreciated but is
 18		not required.
 19
 20    2. Altered source versions must be plainly marked as such, and must not be
 21		misrepresented as being the original software.
 22
 23    3. This notice may not be removed or altered from any source distribution.
 24*/
 25#include "OISWiiMote.h"
 26#include "OISWiiMoteFactoryCreator.h"
 27#include "OISException.h"
 28#include "OISWiiMoteForceFeedback.h"
 29#define _USE_MATH_DEFINES
 30#include <math.h>
 31#include <limits.h>
 32
 33using namespace OIS;
 34
 35//-----------------------------------------------------------------------------------//
 36WiiMote::WiiMote(InputManager* creator, int id, bool buffered, WiiMoteFactoryCreator* local_creator) :
 37	JoyStick("cWiiMote", buffered, id, creator),
 38	mWiiCreator(local_creator),
 39	mtInitialized(false),
 40	mRingBuffer(OIS_WII_EVENT_BUFFER),
 41	mtLastButtonStates(0),
 42	mtLastPOVState(0),
 43	mtLastX(0.0f),
 44	mtLastY(1.0f),
 45	mtLastZ(0.0f),
 46	mtLastNunChuckX(0.0f),
 47	mtLastNunChuckY(1.0f),
 48	mtLastNunChuckZ(0.0f),
 49	mLastNunChuckXAxis(0),
 50	mLastNunChuckYAxis(0),
 51	_mWiiMoteMotionDelay(5),
 52	mRumble(0)
 53{
 54	mRumble = new WiiMoteForceFeedback(mWiiMote);
 55}
 56
 57//-----------------------------------------------------------------------------------//
 58WiiMote::~WiiMote()
 59{
 60	delete mRumble;
 61
 62	if( mWiiMote.IsConnected() )
 63	{
 64		mWiiMote.StopDataStream();
 65		mWiiMote.Disconnect();
 66	}
 67	mWiiCreator->_returnWiiMote(mDevID);
 68}
 69
 70//-----------------------------------------------------------------------------------//
 71void WiiMote::_initialize()
 72{
 73	if( mWiiMote.ConnectToDevice(mDevID) == false )
 74		OIS_EXCEPT(E_InputDisconnected, "Error connecting to WiiMote!");
 75
 76	if( mWiiMote.StartDataStream() == false )
 77		OIS_EXCEPT(E_InputDisconnected, "Error starting WiiMote data stream!");
 78
 79	//Fill in joystick information
 80	mState.mVectors.clear();
 81	mState.mButtons.clear();
 82	mState.mAxes.clear();
 83
 84	if( mWiiMote.IsNunChuckAttached() )
 85	{	//Setup for WiiMote + nunChuck
 86		mState.mVectors.resize(2);
 87		mState.mButtons.resize(9);
 88		mState.mAxes.resize(2);
 89		mState.mAxes[0].absOnly = true;
 90		mState.mAxes[1].absOnly = true;
 91	}
 92	else
 93	{	//Setup for WiiMote
 94		mState.mVectors.resize(1);
 95		mState.mButtons.resize(7);
 96	}
 97
 98	mPOVs = 1;
 99	mState.clear();
100	mtInitialized = true;
101}
102
103//-----------------------------------------------------------------------------------//
104void WiiMote::_threadUpdate()
105{
106	//Leave early if nothing is setup yet
107	if( mtInitialized == false )
108		return;
109
110	//Oops, no room left in ring buffer.. have to wait for client app to call Capture()
111	if( mRingBuffer.GetWriteAvailable() == 0 )
112		return;
113
114	WiiMoteEvent newEvent;
115	newEvent.clear();
116
117	//Update read
118	mWiiMote.HeartBeat();
119
120	//Get & check current button states
121	const cWiiMote::tButtonStatus &bState = mWiiMote.GetLastButtonStatus();
122	_doButtonCheck(bState.m1, 0, newEvent.pushedButtons, newEvent.releasedButtons);	//1
123	_doButtonCheck(bState.m2, 1, newEvent.pushedButtons, newEvent.releasedButtons);	//2
124	_doButtonCheck(bState.mA, 2, newEvent.pushedButtons, newEvent.releasedButtons);	//A
125	_doButtonCheck(bState.mB, 3, newEvent.pushedButtons, newEvent.releasedButtons);	//B
126	_doButtonCheck(bState.mPlus, 4, newEvent.pushedButtons, newEvent.releasedButtons);//+
127	_doButtonCheck(bState.mMinus, 5, newEvent.pushedButtons, newEvent.releasedButtons);//-
128	_doButtonCheck(bState.mHome, 6, newEvent.pushedButtons, newEvent.releasedButtons);//Home
129
130	//Check POV
131	newEvent.povChanged = _doPOVCheck(bState, newEvent.povDirection);
132
133	//Do motion check on main orientation - accounting for sensitivity factor
134	mWiiMote.GetCalibratedAcceleration(newEvent.x, newEvent.y, newEvent.z);
135	//Normalize new vector (old vector is already normalized)
136	float len = sqrt((newEvent.x*newEvent.x) + (newEvent.y*newEvent.y) + (newEvent.z*newEvent.z));
137	newEvent.x /= len;
138	newEvent.y /= len;
139	newEvent.z /= len;
140	
141	//Get new angle
142	float angle = acos((newEvent.x * mtLastX) + (newEvent.y * mtLastY) + (newEvent.z * mtLastZ));
143	if( angle > (mVector3Sensitivity * (M_PI / 180.0)) )
144	{	//Store for next check
145		mtLastX = newEvent.x;
146		mtLastY = newEvent.y;
147		mtLastZ = newEvent.z;
148
149		if( _mWiiMoteMotionDelay <= 0 )
150			newEvent.movement = true; //Set flag as moved
151		else
152			--_mWiiMoteMotionDelay;
153	}
154
155	//Act on NunChuck Data
156	if( mWiiMote.IsNunChuckAttached() )
157	{
158		const cWiiMote::tChuckReport &bState = mWiiMote.GetLastChuckReport();
159		_doButtonCheck(bState.mButtonC, 7, newEvent.pushedButtons, newEvent.releasedButtons); //C
160		_doButtonCheck(bState.mButtonZ, 8, newEvent.pushedButtons, newEvent.releasedButtons); //Z
161
162		mWiiMote.GetCalibratedChuckAcceleration(newEvent.nunChuckx, newEvent.nunChucky, newEvent.nunChuckz);
163		//Normalize new vector (old vector is already normalized)
164		float len = sqrt((newEvent.nunChuckx*newEvent.nunChuckx) + 
165			             (newEvent.nunChucky*newEvent.nunChucky) +
166						 (newEvent.nunChuckz*newEvent.nunChuckz));
167
168		newEvent.nunChuckx /= len;
169		newEvent.nunChucky /= len;
170		newEvent.nunChuckz /= len;
171
172		float angle = acos((newEvent.nunChuckx * mtLastNunChuckX) + 
173			               (newEvent.nunChucky * mtLastNunChuckY) +
174						   (newEvent.nunChuckz * mtLastNunChuckZ));
175
176		if( angle > (mVector3Sensitivity * (M_PI / 180.0)) )
177		{	//Store for next check
178			mtLastNunChuckX = newEvent.nunChuckx;
179			mtLastNunChuckY = newEvent.nunChucky;
180			mtLastNunChuckZ = newEvent.nunChuckz;
181
182			if( _mWiiMoteMotionDelay <= 0 )
183				newEvent.movementChuck = true;
184		}
185
186		//Ok, Now check both NunChuck Joystick axes for movement
187		float tempX = 0.0f, tempY = 0.0f;
188		mWiiMote.GetCalibratedChuckStick(tempX, tempY);
189		
190		//Convert to int and clip
191		newEvent.nunChuckXAxis = (int)(tempX * JoyStick::MAX_AXIS);
192		if( newEvent.nunChuckXAxis > JoyStick::MAX_AXIS )
193			newEvent.nunChuckXAxis = JoyStick::MAX_AXIS;
194		else if( newEvent.nunChuckXAxis < JoyStick::MIN_AXIS )
195			newEvent.nunChuckXAxis = JoyStick::MIN_AXIS;
196
197		newEvent.nunChuckYAxis = (int)(tempY * JoyStick::MAX_AXIS);
198		if( newEvent.nunChuckYAxis > JoyStick::MAX_AXIS )
199			newEvent.nunChuckYAxis = JoyStick::MAX_AXIS;
200		else if( newEvent.nunChuckYAxis < JoyStick::MIN_AXIS )
201			newEvent.nunChuckYAxis = JoyStick::MIN_AXIS;
202
203		//Apply a little dead-zone dampner
204		int xDiff = newEvent.nunChuckXAxis - mLastNunChuckXAxis;
205		if( xDiff > 1500 || xDiff < -1500 )
206		{
207			mLastNunChuckXAxis = newEvent.nunChuckXAxis;
208			newEvent.nunChuckXAxisMoved = true;
209		}
210
211		int yDiff = newEvent.nunChuckYAxis - mLastNunChuckYAxis;
212		if( yDiff > 1500 || yDiff < -1500 )
213		{
214			mLastNunChuckYAxis = newEvent.nunChuckYAxis;
215			newEvent.nunChuckYAxisMoved = true;
216		}
217	}
218
219	//Ok, put entry in ringbuffer if something changed
220	if(newEvent.pushedButtons || newEvent.releasedButtons || newEvent.povChanged || newEvent.movement ||
221	   newEvent.movementChuck || newEvent.nunChuckXAxisMoved || newEvent.nunChuckYAxisMoved)
222	{
223		mRingBuffer.Write(&newEvent, 1);
224	}
225
226	//mWiiMote.PrintStatus();
227}
228
229//-----------------------------------------------------------------------------------//
230void WiiMote::_doButtonCheck(bool new_state, int ois_button, unsigned int &pushed, unsigned int &released)
231{
232	const bool old_state = ((mtLastButtonStates & ( 1L << ois_button )) == 0) ? false : true;
233	
234	//Check to see if new state and old state are the same, and hence, need no change
235	if( new_state == old_state )
236		return;
237
238	//Ok, so it changed... but how?
239	if( new_state )
240	{	//Ok, new state is pushed, old state was not pushed.. so send button press
241		mtLastButtonStates |= 1 << ois_button; //turn the bit flag on
242		pushed |= 1 << ois_button;
243	}
244	else
245	{	//Ok, so new state is not pushed, and old state was pushed.. So, send release
246		mtLastButtonStates &= ~(1 << ois_button); //turn the bit flag off
247		released |= 1 << ois_button;
248	}
249}
250
251//-----------------------------------------------------------------------------------//
252bool WiiMote::_doPOVCheck(const cWiiMote::tButtonStatus &bState, unsigned int &newPosition)
253{
254	newPosition = Pov::Centered;
255
256	if( bState.mUp )
257		newPosition |= Pov::North;
258	else if( bState.mDown )
259		newPosition |= Pov::South;
260
261	if( bState.mLeft )
262		newPosition |= Pov::West;
263	else if( bState.mRight )
264		newPosition |= Pov::East;
265
266	//Was there a change?
267	if( mtLastPOVState != newPosition )
268	{
269		mtLastPOVState = newPosition;
270		return true;
271	}
272
273	return false;
274}
275
276//-----------------------------------------------------------------------------------//
277void WiiMote::setBuffered(bool buffered)
278{
279	mBuffered = buffered;
280}
281
282//-----------------------------------------------------------------------------------//
283void WiiMote::capture()
284{
285	//Anything to read?
286	int entries = mRingBuffer.GetReadAvailable();
287	if( entries <= 0 )
288		return;
289
290	WiiMoteEvent events[OIS_WII_EVENT_BUFFER];
291	if( entries > OIS_WII_EVENT_BUFFER )
292		entries = OIS_WII_EVENT_BUFFER;
293	
294	mRingBuffer.Read(events, entries);
295
296	//Loop through each event
297	for( int i = 0; i < entries; ++i )
298	{
299		//Any movement changes in the main accellerometers?
300		if( events[i].movement )
301		{
302			mState.mVectors[0].x = events[i].x;
303			mState.mVectors[0].y = events[i].y;
304			mState.mVectors[0].z = events[i].z;
305			if( mBuffered && mListener )
306				if( !mListener->vector3Moved( JoyStickEvent( this, mState ), 0 ) ) return;
307		}
308
309		//Check NunChuck movements
310		if( events[i].movementChuck )
311		{
312			mState.mVectors[1].x = events[i].nunChuckx;
313			mState.mVectors[1].y = events[i].nunChucky;
314			mState.mVectors[1].z = events[i].nunChuckz;
315			if( mBuffered && mListener )
316				if( !mListener->vector3Moved( JoyStickEvent( this, mState ), 1 ) ) return;
317		}
318
319		if( events[i].nunChuckXAxisMoved )
320		{
321			mState.mAxes[0].abs = events[i].nunChuckXAxis;
322
323			if( mBuffered && mListener )
324				if( !mListener->axisMoved( JoyStickEvent( this, mState ), 0 ) ) return;
325		}
326
327		if( events[i].nunChuckYAxisMoved )
328		{
329			mState.mAxes[1].abs = events[i].nunChuckYAxis;
330
331			if( mBuffered && mListener )
332				if( !mListener->axisMoved( JoyStickEvent( this, mState ), 1 ) ) return;
333		}
334
335		//Has the hat swtich changed?
336		if( events[i].povChanged )
337		{
338			mState.mPOV[0].direction = events[i].povDirection;
339			if( mBuffered && mListener )
340				if( !mListener->povMoved( JoyStickEvent( this, mState ), 0 ) ) return;
341		}
342
343		//Check for any pushed/released events for each button bit
344		int buttons = (int)mState.mButtons.size();
345		for( int b = 0; b < buttons; ++b )
346		{
347			unsigned bit_flag = 1 << b;
348			if( (events[i].pushedButtons & bit_flag) != 0 )
349			{	//send event
350				mState.mButtons[b] = true;
351				if( mBuffered && mListener )
352					if( !mListener->buttonPressed( JoyStickEvent( this, mState ), b ) ) return;
353			}
354
355			if( (events[i].releasedButtons & bit_flag) != 0 )
356			{	//send event
357				mState.mButtons[b] = false;
358				if( mBuffered && mListener )
359					if( !mListener->buttonReleased( JoyStickEvent( this, mState ), b ) ) return;
360			}
361		}
362	}
363}
364
365//-----------------------------------------------------------------------------------//
366Interface* WiiMote::queryInterface(Interface::IType type)
367{
368	if( type == Interface::ForceFeedback && mtInitialized )
369		return mRumble;
370
371	return 0;
372}
373#endif