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