VMotionTrack.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. //-----------------------------------------------------------------------------
  2. // Verve
  3. // Copyright (C) 2014 - Violent Tulip
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to
  7. // deal in the Software without restriction, including without limitation the
  8. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9. // sell copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. // IN THE SOFTWARE.
  22. //-----------------------------------------------------------------------------
  23. #include "Verve/Core/VGroup.h"
  24. #include "Verve/Extension/Motion/VMotionTrack.h"
  25. #include "Verve/Extension/Motion/VMotionEvent.h"
  26. #include "console/consoleTypes.h"
  27. //-----------------------------------------------------------------------------
  28. IMPLEMENT_CONOBJECT( VMotionTrack );
  29. //-----------------------------------------------------------------------------
  30. VMotionTrack::VMotionTrack( void ) :
  31. mDataReference( String::EmptyString ),
  32. mOrientationMode( "FREE" ),
  33. mOrientationData( String::EmptyString ),
  34. mRelative( false )
  35. {
  36. setLabel( "MotionTrack" );
  37. }
  38. void VMotionTrack::initPersistFields( void )
  39. {
  40. Parent::initPersistFields();
  41. addField( "Reference", TypeRealString, Offset( mDataReference, VMotionTrack ), "The name of the data field referencing the object to be attached to the path." );
  42. addProtectedField( "OrientationMode", TypeRealString, Offset( mOrientationMode, VMotionTrack ), &setOrientationMode, &defaultProtectedGetFn, "The orientation mode of the object attached to the path." );
  43. addProtectedField( "OrientationData", TypeRealString, Offset( mOrientationData, VMotionTrack ), &setOrientationData, &defaultProtectedGetFn, "The name of the data field holding the orientation data (used for Orientation Modes, ToObject & ToPoint)." );
  44. addField( "Relative", TypeBool, Offset( mRelative, VMotionTrack ), "Attach the object with an offset based on its initial position." );
  45. }
  46. //-----------------------------------------------------------------------------
  47. //
  48. // Controller Methods.
  49. //
  50. //-----------------------------------------------------------------------------
  51. //-----------------------------------------------------------------------------
  52. //
  53. // VMotionTrack::onControllerEvent( pEvent );
  54. //
  55. // When the controller's state changes, this method is called. If the
  56. // controller is paused, then the path object will cease to move. If the
  57. // controller resumes play, the object will continue on its path.
  58. //
  59. // For a full list of possible events, see the 'eControllerEventType'
  60. // declaration in VController.h.
  61. //
  62. //-----------------------------------------------------------------------------
  63. bool VMotionTrack::onControllerEvent( VController::eControllerEventType pEvent )
  64. {
  65. if ( !Parent::onControllerEvent( pEvent ) )
  66. {
  67. // Skip.
  68. return false;
  69. }
  70. // Enabled?
  71. if ( !isEnabled() )
  72. {
  73. // Continue Processing Events.
  74. return true;
  75. }
  76. // Fetch Path & Reference Object.
  77. VTorque::PathObjectType *path = getPath();
  78. VTorque::SceneObjectType *object = getSceneObject();
  79. if ( !path || !object || !VTorque::isPathObjectAttached( path, object ) )
  80. {
  81. // Invalid.
  82. return true;
  83. }
  84. switch ( pEvent )
  85. {
  86. case VController::k_EventPlay :
  87. {
  88. // Continue Advancing.
  89. VTorque::setPathObjectActive( path, object, true );
  90. } break;
  91. case VController::k_EventPause :
  92. {
  93. // Stop Advancing.
  94. VTorque::setPathObjectActive( path, object, false );
  95. } break;
  96. case VController::k_EventStop :
  97. {
  98. // Detach the Object.
  99. detachObject();
  100. } break;
  101. }
  102. return true;
  103. }
  104. //-----------------------------------------------------------------------------
  105. //
  106. // VMotionTrack::onControllerReset( pTime, pForward );
  107. //
  108. // Reposition the path object on the path appropriately. The position is
  109. // interpolated between two nodes, the last node and the next node. These
  110. // correspond to the last and current events.
  111. //
  112. //-----------------------------------------------------------------------------
  113. void VMotionTrack::onControllerReset( const S32 &pTime, const bool &pForward )
  114. {
  115. // Parent Reset.
  116. Parent::onControllerReset( pTime, pForward );
  117. // Valid Track?
  118. // Note: We must have at least 2 Events/Nodes to path.
  119. if ( size() < 2 )
  120. {
  121. // Invalid.
  122. return;
  123. }
  124. // Get Object References.
  125. VController *controller = getController();
  126. VTorque::PathObjectType *path = getPath();
  127. VTorque::SceneObjectType *object = getSceneObject();
  128. if ( !controller || !path || !object )
  129. {
  130. // Invalid Object(s).
  131. return;
  132. }
  133. // Attached?
  134. if ( !VTorque::isPathObjectAttached( path, object ) )
  135. {
  136. // No, Attach Now.
  137. attachObject();
  138. }
  139. // Reset Object.
  140. resetObject( pTime );
  141. }
  142. //-----------------------------------------------------------------------------
  143. //
  144. // Reference Methods.
  145. //
  146. //-----------------------------------------------------------------------------
  147. //-----------------------------------------------------------------------------
  148. //
  149. // VMotionTrack::getPath();
  150. //
  151. // Returns the path that this track is referencing.
  152. //
  153. //-----------------------------------------------------------------------------
  154. VTorque::PathObjectType *VMotionTrack::getPath( void )
  155. {
  156. // Fetch the Controller.
  157. VController *controller = getController();
  158. if ( !controller )
  159. {
  160. // Invalid Controller.
  161. return NULL;
  162. }
  163. // Evalulate the Data Field.
  164. String fieldValue;
  165. if ( controller->getDataValue( mDataReference, fieldValue ) )
  166. {
  167. // Return Object.
  168. return dynamic_cast<VTorque::PathObjectType*>( Sim::findObject( fieldValue ) );
  169. }
  170. // No Data!
  171. return NULL;
  172. }
  173. //-----------------------------------------------------------------------------
  174. //
  175. // VMotionTrack::attachObject();
  176. //
  177. // Attach the underlying Scene Object to the target Path at the first Node.
  178. // Default settings are applied and must be updated after the object is
  179. // attached.
  180. //
  181. //-----------------------------------------------------------------------------
  182. void VMotionTrack::attachObject( void )
  183. {
  184. // Get Object References.
  185. VTorque::PathObjectType *path = getPath();
  186. VTorque::SceneObjectType *object = getSceneObject();
  187. if ( !path || !object )
  188. {
  189. // Invalid Object(s).
  190. return;
  191. }
  192. // Object Attached?
  193. if ( VTorque::isPathObjectAttached( path, object ) )
  194. {
  195. // Already Attached.
  196. return;
  197. }
  198. // Fetch Forwards.
  199. const bool &forward = isControllerPlayingForward();
  200. // Select the Node.
  201. const S32 node = ( forward ) ? 0 : ( size() - 1 );
  202. // Fetch the value from the controller data table.
  203. String orientationDataValue = String::EmptyString;
  204. if ( mOrientationData != String::EmptyString
  205. && !getController()->getDataValue( mOrientationData, orientationDataValue ) )
  206. {
  207. // Sanity!
  208. Con::warnf( "Unable to located the value for the given orientation data key, '%s'", mOrientationData.c_str() );
  209. // Clear.
  210. orientationDataValue = String::EmptyString;
  211. }
  212. // Attach Object.
  213. VTorque::attachPathObject( path, object, forward, mRelative, node, -1, mOrientationMode, orientationDataValue );
  214. }
  215. //-----------------------------------------------------------------------------
  216. //
  217. // VMotionTrack::detachObject( void );
  218. //
  219. //
  220. //
  221. //-----------------------------------------------------------------------------
  222. void VMotionTrack::detachObject( void )
  223. {
  224. // Get Object References.
  225. VTorque::PathObjectType *path = getPath();
  226. VTorque::SceneObjectType *object = getSceneObject();
  227. if ( !path || !object )
  228. {
  229. // Invalid Object(s).
  230. return;
  231. }
  232. // Object Attached?
  233. if ( !VTorque::isPathObjectAttached( path, object ) )
  234. {
  235. // Not Attached.
  236. return;
  237. }
  238. // Detach.
  239. VTorque::detachPathObject( path, object );
  240. }
  241. //-----------------------------------------------------------------------------
  242. //
  243. // VMotionTrack::resetObject( pTime );
  244. //
  245. //
  246. //
  247. //-----------------------------------------------------------------------------
  248. void VMotionTrack::resetObject( const S32 &pTime )
  249. {
  250. // Get Object References.
  251. VTorque::PathObjectType *path = getPath();
  252. VTorque::SceneObjectType *object = getSceneObject();
  253. if ( !path || !object )
  254. {
  255. // Invalid Object(s).
  256. return;
  257. }
  258. // Fetch Controller Info.
  259. const bool &isPlaying = isControllerPlaying();
  260. const bool &isPlayingForward = isControllerPlayingForward();
  261. const bool &isLooping = isControllerLooping();
  262. // Init Variables.
  263. bool objectActive = false;
  264. F32 objectInterp = 0.f;
  265. F32 objectSpeed = 0.f;
  266. S32 srcNodeIndex = 0;
  267. S32 dstNodeIndex = 0;
  268. VMotionEvent *event;
  269. if ( !getNextEvent( event ) || event->getTriggerTime() == pTime )
  270. {
  271. // Note: This case deals with a target time that is greater than the
  272. // trigger time of the Last Event on this track. It will clamp
  273. // the position of the object to the corresponding node of the
  274. // Last Event.
  275. // Note: If pTime is exactly equal to the Next Event's trigger time,
  276. // then it will set the Source Node to the Last Node and
  277. // set its Interp to 0.f - which is incorrect!
  278. if ( !event || event->getTriggerTime() != pTime )
  279. {
  280. // Fetch the Last Event.
  281. getPreviousEvent( event );
  282. }
  283. // Set the Info.
  284. objectInterp = 0.f;
  285. objectSpeed = event->getObjectSpeed();
  286. srcNodeIndex = event->getNodeIndex();
  287. dstNodeIndex = srcNodeIndex;
  288. }
  289. else if ( !event->getPreviousEvent() )
  290. {
  291. // Note: This case deals with a target time that is less than the
  292. // trigger time of the First Event on this track. It will clamp
  293. // the position of the object to the corresponding node of the
  294. // First Event.
  295. // Set the Info.
  296. objectInterp = 0.f;
  297. objectSpeed = event->getObjectSpeed();
  298. srcNodeIndex = event->getNodeIndex();
  299. dstNodeIndex = srcNodeIndex;
  300. }
  301. else
  302. {
  303. // Note: This case deals with a target time that is between two Events
  304. // on this track. It will position the object on the path,
  305. // between the two nodes corresponding to the Events.
  306. // Fetch the Last Event.
  307. VMotionEvent *lastEvent;
  308. getPreviousEvent( lastEvent );
  309. // Set the Info.
  310. objectActive = isPlaying;
  311. objectInterp = calculateInterp( pTime );
  312. objectSpeed = lastEvent->getObjectSpeed();
  313. srcNodeIndex = event->getNodeIndex( ( isPlayingForward ) ? -1 : 1 );
  314. dstNodeIndex = event->getNodeIndex();
  315. }
  316. // Set Active.
  317. VTorque::setPathObjectActive( path, object, objectActive );
  318. // Set Forward.
  319. VTorque::setPathObjectForward( path, object, isPlayingForward );
  320. // Set Speed.
  321. VTorque::setPathObjectSpeed( path, object, objectSpeed );
  322. // Set Current Node.
  323. VTorque::setPathObjectNode( path, object, srcNodeIndex );
  324. // Set End Node.
  325. VTorque::setPathObjectEndNode( path, object, ( ( isLooping ) ? -1 : ( size() - 1 ) ) );
  326. // Set Interp.
  327. VTorque::setPathObjectInterp( path, object, objectInterp );
  328. }
  329. //-----------------------------------------------------------------------------
  330. //
  331. // Static Field Methods.
  332. //
  333. //-----------------------------------------------------------------------------
  334. bool VMotionTrack::setOrientationMode( void *pObject, const char *pArray, const char *pData )
  335. {
  336. // Fetch Track.
  337. VMotionTrack *track = static_cast<VMotionTrack*>( pObject );
  338. // Store Data.
  339. track->mOrientationMode = pData;
  340. VTorque::PathObjectType *path = track->getPath();
  341. VTorque::SceneObjectType *object = track->getSceneObject();
  342. if ( VTorque::isPathObjectAttached( path, object ) )
  343. {
  344. // Set Orientation Mode.
  345. VTorque::setPathObjectOrientation( path, object, track->mOrientationMode, track->mOrientationData );
  346. }
  347. return false;
  348. }
  349. bool VMotionTrack::setOrientationData( void *pObject, const char *pArray, const char *pData )
  350. {
  351. // Fetch Track.
  352. VMotionTrack *track = static_cast<VMotionTrack*>( pObject );
  353. // Store Data.
  354. track->mOrientationData = pData;
  355. VTorque::PathObjectType *path = track->getPath();
  356. VTorque::SceneObjectType *object = track->getSceneObject();
  357. if ( VTorque::isPathObjectAttached( path, object ) )
  358. {
  359. // Set Orientation Mode.
  360. VTorque::setPathObjectOrientation( path, object, track->mOrientationMode, track->mOrientationData );
  361. }
  362. return false;
  363. }
  364. #ifdef VT_EDITOR
  365. //-----------------------------------------------------------------------------
  366. //
  367. // Debug Methods.
  368. //
  369. //-----------------------------------------------------------------------------
  370. DefineEngineMethod( VMotionTrack, getPath, S32, (),, "( void ) - Get the path object this track references.\n"
  371. "@return Returns the SimObjectID for the object." )
  372. {
  373. // Fetch Path.
  374. SimObject *pathReference = object->getPath();
  375. // Return.
  376. return ( pathReference ) ? pathReference->getId() : 0;
  377. }
  378. #endif