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