Torque3D Documentation / _generateds / VMotionTrack.cpp

VMotionTrack.cpp

Engine/source/Verve/Extension/Motion/VMotionTrack.cpp

More...

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