VMotion.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  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/Torque/TMotion.h"
  24. #include "Verve/VPath/VPath.h"
  25. //-----------------------------------------------------------------------------
  26. // Sync the local connection when editing path objects?
  27. // Note: This was originally done so that editing was very smooth, but it turns
  28. // out that any lag was due to errors in the pathing operations
  29. // themselves. If issues persist, then uncomment this definition and you
  30. // might see a marked improvement in performance while editing in Verve.
  31. //#define VT_SYNC_LOCALCLIENT
  32. //-----------------------------------------------------------------------------
  33. //
  34. // Utility Methods.
  35. //
  36. //-----------------------------------------------------------------------------
  37. NetObject *getClientObject( NetObject *pObject )
  38. {
  39. if ( !pObject )
  40. {
  41. return NULL;
  42. }
  43. NetConnection *toServer = NetConnection::getConnectionToServer();
  44. NetConnection *toClient = NetConnection::getLocalClientConnection();
  45. if ( !toServer || !toClient )
  46. {
  47. return NULL;
  48. }
  49. const S32 ghostIndex = toClient->getGhostIndex( pObject );
  50. if ( ghostIndex == -1 )
  51. {
  52. return NULL;
  53. }
  54. return toServer->resolveGhost( ghostIndex );
  55. }
  56. void _attachPathObject( VPath *pPath, SceneObject *pObject, const bool &pForward, const bool &pRelative, const S32 &pStartNodeIndex, const S32 &pEndNodeIndex, const String &pOrientation, const String &pOrientationData )
  57. {
  58. if ( pOrientation == String::EmptyString )
  59. {
  60. // Attach Object.
  61. pPath->attachObject( pObject, pForward, 0.f, pRelative, pStartNodeIndex, pEndNodeIndex );
  62. // Quit.
  63. return;
  64. }
  65. // Fetch Orientation.
  66. const VPathObject::eOrientationType type = VPathObject::getOrientationTypeEnum( pOrientation );
  67. switch ( type )
  68. {
  69. case VPathObject::k_OrientationFree :
  70. case VPathObject::k_OrientationInterpolate :
  71. case VPathObject::k_OrientationToPath :
  72. {
  73. // Attach Object.
  74. pPath->attachObject( pObject, pForward, 0.f, pRelative, pStartNodeIndex, pEndNodeIndex, type, NULL );
  75. } break;
  76. case VPathObject::k_OrientationToObject :
  77. {
  78. // Fetch Object.
  79. SceneObject *lookAtObject = dynamic_cast<SceneObject*>( Sim::findObject( pOrientationData ) );
  80. // Valid Object?
  81. if ( lookAtObject != NULL )
  82. {
  83. // Attach Object.
  84. pPath->attachObject( pObject, pForward, 0.f, pRelative, pStartNodeIndex, pEndNodeIndex, type, (void*)lookAtObject );
  85. }
  86. } break;
  87. case VPathObject::k_OrientationToPoint:
  88. {
  89. // Fetch Point.
  90. Point3F lookAtPoint( 0.f, 0.f, 0.f );
  91. if ( dSscanf( pOrientationData, "%g %g %g", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ) == 3 )
  92. {
  93. // Attach Object.
  94. pPath->attachObject( pObject, pForward, 0.f, pRelative, pStartNodeIndex, pEndNodeIndex, type, (void*)lookAtPoint );
  95. }
  96. } break;
  97. }
  98. }
  99. //-----------------------------------------------------------------------------
  100. //
  101. // Path Methods.
  102. //
  103. //-----------------------------------------------------------------------------
  104. bool VTorque::isMovable( SimObject *pObject )
  105. {
  106. return ( dynamic_cast<SceneObjectType*>( pObject ) != NULL );
  107. }
  108. bool VTorque::isPath( SimObject *pObject )
  109. {
  110. return ( dynamic_cast<PathObjectType*>( pObject ) != NULL );
  111. }
  112. bool VTorque::isPathObjectAttached( PathObjectType *pPath, SceneObjectType *pObject )
  113. {
  114. if ( !pPath || !pObject )
  115. {
  116. // Sanity!
  117. return false;
  118. }
  119. // Return.
  120. return pPath->isObjectAttached( pObject );
  121. }
  122. F32 VTorque::getPathNodeLength( PathObjectType *pPath, const S32 &pNode )
  123. {
  124. if ( !pPath )
  125. {
  126. // Sanity!
  127. return false;
  128. }
  129. // Normalize Node Index.
  130. S32 nodeIndex = pNode;
  131. pPath->normalizeNodeIndex( nodeIndex );
  132. // Fetch Node.
  133. VPathNode *node = pPath->getNode( nodeIndex );
  134. // Return Length.
  135. return node->getLength();
  136. }
  137. void VTorque::attachPathObject( PathObjectType *pPath, SceneObjectType *pObject, const bool &pForward, const bool &pRelative, const S32 &pStartNodeIndex, const S32 &pEndNodeIndex, const String &pOrientation, const String &pOrientationData )
  138. {
  139. if ( !pPath || !pObject )
  140. {
  141. // Sanity!
  142. return;
  143. }
  144. // Attach Object.
  145. _attachPathObject( pPath, pObject, pForward, pRelative, pStartNodeIndex, pEndNodeIndex, pOrientation, pOrientationData );
  146. #if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT )
  147. // Fetch the client Path.
  148. VPath *clientPath = dynamic_cast<VPath*>( getClientObject( pPath ) );
  149. SceneObjectType *clientObject = dynamic_cast<SceneObjectType*>( getClientObject( pObject ) );
  150. if ( clientPath && clientObject )
  151. {
  152. // Attach Object.
  153. _attachPathObject( clientPath, clientObject, pForward, pRelative, pStartNodeIndex, pEndNodeIndex, pOrientation, pOrientationData );
  154. }
  155. #endif
  156. }
  157. void VTorque::detachPathObject( PathObjectType *pPath, SceneObjectType *pObject )
  158. {
  159. if ( !pPath || !pObject )
  160. {
  161. // Sanity!
  162. return;
  163. }
  164. // Detach Object.
  165. pPath->detachObject( pObject );
  166. #if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT )
  167. // Fetch the client Path.
  168. VPath *clientPath = dynamic_cast<VPath*>( getClientObject( pPath ) );
  169. SceneObjectType *clientObject = dynamic_cast<SceneObjectType*>( getClientObject( pObject ) );
  170. if ( clientPath && clientObject )
  171. {
  172. // Detach Object.
  173. clientPath->detachObject( clientObject );
  174. }
  175. #endif
  176. }
  177. void VTorque::setPathObjectActive( PathObjectType *pPath, SceneObjectType *pObject, const bool &pActive )
  178. {
  179. if ( !pPath || !pObject )
  180. {
  181. // Sanity!
  182. return;
  183. }
  184. // Update Object State.
  185. pPath->setPathObjectActive( pObject, pActive );
  186. #if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT )
  187. // Fetch the client Path.
  188. VPath *clientPath = dynamic_cast<VPath*>( getClientObject( pPath ) );
  189. SceneObjectType *clientObject = dynamic_cast<SceneObjectType*>( getClientObject( pObject ) );
  190. if ( clientPath && clientObject )
  191. {
  192. // Update Object State.
  193. clientPath->setPathObjectActive( clientObject, pActive );
  194. }
  195. #endif
  196. }
  197. void VTorque::setPathObjectInterp( PathObjectType *pPath, SceneObjectType *pObject, const F32 &pInterp )
  198. {
  199. if ( !pPath || !pObject )
  200. {
  201. // Sanity!
  202. return;
  203. }
  204. // Update Path Object Interp.
  205. pPath->setPathObjectInterp( pObject, pInterp );
  206. #if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT )
  207. // Fetch the client Path.
  208. VPath *clientPath = dynamic_cast<VPath*>( getClientObject( pPath ) );
  209. SceneObjectType *clientObject = dynamic_cast<SceneObjectType*>( getClientObject( pObject ) );
  210. if ( clientPath && clientObject )
  211. {
  212. // Apply the same action.
  213. clientPath->setPathObjectInterp( clientObject, pInterp );
  214. }
  215. #endif
  216. }
  217. void VTorque::setPathObjectOffset( PathObjectType *pPath, SceneObjectType *pObject, const Point3F &pOffset )
  218. {
  219. if ( !pPath || !pObject )
  220. {
  221. // Sanity!
  222. return;
  223. }
  224. // Update Path Object Offset.
  225. pPath->setPathObjectOffset( pObject, pOffset );
  226. #if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT )
  227. // Fetch the client Path.
  228. VPath *clientPath = dynamic_cast<VPath*>( getClientObject( pPath ) );
  229. SceneObjectType *clientObject = dynamic_cast<SceneObjectType*>( getClientObject( pObject ) );
  230. if ( clientPath && clientObject )
  231. {
  232. // Apply the same action.
  233. clientPath->setPathObjectOffset( clientObject, pOffset );
  234. }
  235. #endif
  236. }
  237. void VTorque::setPathObjectSpeed( PathObjectType *pPath, SceneObjectType *pObject, const F32 &pSpeed )
  238. {
  239. if ( !pPath || !pObject )
  240. {
  241. // Sanity!
  242. return;
  243. }
  244. // Update Path Speed.
  245. pPath->setPathObjectSpeed( pObject, pSpeed );
  246. #if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT )
  247. // Fetch the client Path.
  248. VPath *clientPath = dynamic_cast<VPath*>( getClientObject( pPath ) );
  249. SceneObjectType *clientObject = dynamic_cast<SceneObjectType*>( getClientObject( pObject ) );
  250. if ( clientPath && clientObject )
  251. {
  252. // Apply the same action.
  253. clientPath->setPathObjectSpeed( clientObject, pSpeed );
  254. }
  255. #endif
  256. }
  257. void VTorque::setPathObjectOrientation( PathObjectType *pPath, SceneObjectType *pObject, const String &pOrientation, const String &pOrientationData )
  258. {
  259. if ( !pPath || !pObject )
  260. {
  261. // Sanity!
  262. return;
  263. }
  264. // Set the orientation mode.
  265. // Note: Call the console method so we don't have to handle all the different modes here.
  266. Con::executef( pPath, "setPathObjectOrientationMode", pObject->getIdString(), pOrientation, pOrientationData );
  267. #if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT )
  268. // TODO: Handle synching the client path immediately.
  269. #endif
  270. /*
  271. // Set the Default Mode.
  272. if ( pOrientation == String::EmptyString )
  273. {
  274. // Apply Mode.
  275. pPath->setPathObjectOrientationMode( pObject, VPathObject::k_OrientationToPath );
  276. return;
  277. }
  278. // Fetch Orientation.
  279. const VPathObject::eOrientationType type = VPathObject::getOrientationTypeEnum( pOrientation );
  280. switch ( type )
  281. {
  282. case VPathObject::k_OrientationFree :
  283. case VPathObject::k_OrientationInterpolate :
  284. case VPathObject::k_OrientationToPath :
  285. {
  286. // Apply Mode.
  287. pPath->setPathObjectOrientationMode( pObject, type );
  288. } break;
  289. case VPathObject::k_OrientationToObject :
  290. {
  291. // Fetch Object.
  292. SceneObjectType *lookAtObject;
  293. if ( !Sim::findObject( pOrientationData, lookAtObject ) )
  294. {
  295. // Invalid Object.
  296. return;
  297. }
  298. // Apply Mode.
  299. pPath->setPathObjectOrientationMode( pObject, type, lookAtObject );
  300. } break;
  301. case VPathObject::k_OrientationToPoint:
  302. {
  303. // Fetch Point.
  304. Point3F lookAtPoint( 0.f, 0.f, 0.f );
  305. dSscanf( pOrientationData, "%g %g %g", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z );
  306. // Apply Mode.
  307. pPath->setPathObjectOrientationMode( pObject, type, lookAtPoint );
  308. } break;
  309. }
  310. */
  311. }
  312. void VTorque::setPathObjectForward( PathObjectType *pPath, SceneObjectType *pObject, const bool &pForward )
  313. {
  314. if ( !pPath || !pObject )
  315. {
  316. // Sanity!
  317. return;
  318. }
  319. // Update Path Object Forward.
  320. pPath->setPathObjectForward( pObject, pForward );
  321. #if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT )
  322. // Fetch the client Path.
  323. VPath *clientPath = dynamic_cast<VPath*>( getClientObject( pPath ) );
  324. SceneObjectType *clientObject = dynamic_cast<SceneObjectType*>( getClientObject( pObject ) );
  325. if ( clientPath && clientObject )
  326. {
  327. // Apply the same action.
  328. clientPath->setPathObjectForward( clientObject, pForward );
  329. }
  330. #endif
  331. }
  332. void VTorque::setPathObjectNode( PathObjectType *pPath, SceneObjectType *pObject, const S32 &pNode )
  333. {
  334. if ( !pPath || !pObject )
  335. {
  336. // Sanity!
  337. return;
  338. }
  339. // Update Object Current Node.
  340. pPath->setPathObjectNode( pObject, pNode );
  341. #if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT )
  342. // Fetch the client Path.
  343. VPath *clientPath = dynamic_cast<VPath*>( getClientObject( pPath ) );
  344. SceneObjectType *clientObject = dynamic_cast<SceneObjectType*>( getClientObject( pObject ) );
  345. if ( clientPath && clientObject )
  346. {
  347. // Update Object Current Node.
  348. clientPath->setPathObjectNode( clientObject, pNode );
  349. }
  350. #endif
  351. }
  352. void VTorque::setPathObjectEndNode( PathObjectType *pPath, SceneObjectType *pObject, const S32 &pNode )
  353. {
  354. if ( !pPath || !pObject )
  355. {
  356. // Sanity!
  357. return;
  358. }
  359. // Update Object End Node.
  360. pPath->setPathObjectEndNode( pObject, pNode );
  361. #if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT )
  362. // Fetch the client Path.
  363. VPath *clientPath = dynamic_cast<VPath*>( getClientObject( pPath ) );
  364. SceneObjectType *clientObject = dynamic_cast<SceneObjectType*>( getClientObject( pObject ) );
  365. if ( clientPath && clientObject )
  366. {
  367. // Update Object End Node.
  368. clientPath->setPathObjectEndNode( clientObject, pNode );
  369. }
  370. #endif
  371. }