VTrack.cpp

Engine/source/Verve/Core/VTrack.cpp

More...

Public Functions

Detailed Description

Public Functions

IMPLEMENT_CONOBJECT(VTrack )

  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/VTrack.h"
 25#include "Verve/Core/VGroup.h"
 26#include "Verve/Core/VController.h"
 27#include "math/mMath.h"
 28
 29//-----------------------------------------------------------------------------
 30IMPLEMENT_CONOBJECT( VTrack );
 31//-----------------------------------------------------------------------------
 32
 33VTrack::VTrack( void ) :
 34        mNextEvent( NULL )
 35{
 36    setLabel( "DefaultTrack" );
 37}
 38
 39//-----------------------------------------------------------------------------
 40//
 41// Tree Methods.
 42//
 43//-----------------------------------------------------------------------------
 44
 45//-----------------------------------------------------------------------------
 46// 
 47// VTrack::onAttach();
 48// 
 49// This callback subscribes this object to the controller's event signal.
 50// 
 51//-----------------------------------------------------------------------------
 52void VTrack::onAttach( void )
 53{
 54    Parent::onAttach();
 55
 56    // Valid Controller?
 57    if ( getController() )
 58    {
 59        // Subscribe to Updates.
 60        getController()->getControllerUpdateSignal().notify( this, &VTrack::onControllerUpdate );
 61
 62        // Subscribe to Events.
 63        getController()->getControllerEventSignal().notify( this, &VTrack::onControllerEvent );
 64    }
 65}
 66
 67//-----------------------------------------------------------------------------
 68// 
 69// VTrack::onAttach();
 70// 
 71// This callback removes this object from the controller's event signal
 72// notification list.
 73// 
 74//-----------------------------------------------------------------------------
 75void VTrack::onDetach( void )
 76{
 77    // Valid Controller?
 78    if ( getController() )
 79    {
 80        // Remove Update Notification.
 81        getController()->getControllerUpdateSignal().remove( this, &VTrack::onControllerUpdate );
 82
 83        // Remove Event Notification.
 84        getController()->getControllerEventSignal().remove( this, &VTrack::onControllerEvent );
 85    }
 86
 87    Parent::onDetach();
 88}
 89
 90//-----------------------------------------------------------------------------
 91//
 92// Controller Methods.
 93//
 94//-----------------------------------------------------------------------------
 95
 96//-----------------------------------------------------------------------------
 97// 
 98// VTrack::onControllerUpdate( pTime, pDelta );
 99// 
100// The Next Event is integrated until has finished its execution. Once it has
101// finished, the next event to be triggered becomes the Current Event. Doing
102// this means that only one event is ever checked to see if it should be
103// triggered.
104// 
105//-----------------------------------------------------------------------------
106void VTrack::onControllerUpdate( const S32 &pTime, const S32 &pDelta )
107{
108    if ( !isEnabled() || !mNextEvent )
109    {
110        // Don't Update.
111        return;
112    }
113
114    // Update Next Event.
115    while ( !mNextEvent->onControllerUpdate( pTime, pDelta ) )
116    {
117        // Next Event?
118        if ( !updateNextEvent() )
119        {
120            // No Valid Events.
121            mNextEvent = NULL;
122            break;
123        }
124    }
125}
126
127//-----------------------------------------------------------------------------
128// 
129// VTrack::onControllerEvent( pEvent );
130// 
131// When the controller's state changes, this method is called. If the
132// controller is reset the virtual method, onControllerReset is called.
133// 
134// For a full list of possible events, see the 'eControllerEventType'
135// declaration in VController.h.
136// 
137//-----------------------------------------------------------------------------
138bool VTrack::onControllerEvent( VController::eControllerEventType pEvent )
139{
140    if ( !getController() )
141    {
142        AssertFatal( false, "VTrack::onControllerEvent() - Invalid Controller." );
143        return false;
144    }
145
146    // Enabled?
147    if ( !isEnabled() )
148    {
149        // Continue Processing Events.
150        return true;
151    }
152
153    switch( pEvent )
154    {
155        case VController::k_EventReset :
156            {
157
158                // Reset.
159                onControllerReset( getControllerTime(), isControllerPlayingForward() );
160
161            } break;
162    }
163
164    // Continue Processing Events.
165    return true;
166}
167
168//-----------------------------------------------------------------------------
169// 
170// VTrack::onControllerReset( pTime, pForward );
171// 
172// Reset the status of the track. The Next Event is allocated here.
173// 
174//-----------------------------------------------------------------------------
175void VTrack::onControllerReset( const S32 &pTime, const bool &pForward )
176{
177    // Clear Next Event.
178    mNextEvent = NULL;
179
180    for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode )
181    {
182        VEvent *event = ( VEvent* )node;
183
184        // Reset Event.
185        event->onControllerReset( pTime, pForward );
186
187        if ( ( event->isPlaying() )
188             || ( pForward && event->getTriggerTime() >= pTime ) )
189        {
190            if ( !mNextEvent )
191            {
192                // Use as Next Event.
193                mNextEvent = event;
194            }
195        }
196        else if ( !pForward && pTime >= event->getTriggerTime() )
197        {
198            VEvent *nextEvent = ( VEvent* )node->mSiblingNextNode;
199            if ( !nextEvent || pTime < nextEvent->getTriggerTime() )
200            {
201                // Use as Next Event.
202                mNextEvent = event;
203            }
204        }
205    }
206}
207
208//-----------------------------------------------------------------------------
209//
210// Reference Methods.
211//
212//-----------------------------------------------------------------------------
213
214//-----------------------------------------------------------------------------
215// 
216// VTrack::sort();
217// 
218// Sort the track's events by the event's trigger time.
219// 
220//-----------------------------------------------------------------------------
221void VTrack::sort( void )
222{
223    const S32 count = size();
224    for ( S32 j = 0; j < count; j++ )
225    {
226        for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode )
227        {
228            VEvent *eventA = ( VEvent* )node;
229            VEvent *eventB = ( VEvent* )node->mSiblingNextNode;
230            if ( !eventB )
231            {
232                // No Node.
233                break;
234            }
235
236            // Swap?
237            if ( eventA->getTriggerTime() > eventB->getTriggerTime() )
238            {
239                // Get Outer Siblings.
240                ITreeNode *prevNode = eventA->mSiblingPrevNode;
241                ITreeNode *nextNode = eventB->mSiblingNextNode;
242                
243                if ( eventA->mParentNode && eventA->mParentNode->mChildNode == eventA )
244                {
245                    // New Child Node.
246                    eventA->mParentNode->mChildNode = eventB;
247                }
248
249                //
250                // Move A.
251                eventA->mSiblingPrevNode = eventB;
252                eventA->mSiblingNextNode = nextNode;
253
254                if ( nextNode )
255                {
256                    // Update Outer Sibling.
257                    nextNode->mSiblingPrevNode = eventA;
258                }
259
260                //
261                // Move B.
262
263                eventB->mSiblingPrevNode = prevNode;
264                eventB->mSiblingNextNode = eventA;
265
266                if ( prevNode )
267                {
268                    // Update Outer Sibling.
269                    prevNode->mSiblingNextNode = eventB;
270                }
271            }
272        }
273    }
274}
275
276//-----------------------------------------------------------------------------
277// 
278// VTrack::updateNextEvent( pForward );
279// 
280// Point mNextEvent to the next valid event in the track's sequence.
281// 
282//-----------------------------------------------------------------------------
283bool VTrack::updateNextEvent( void )
284{
285    if ( !mNextEvent )
286    {
287        // Invalid Event.
288        return false;
289    }
290
291    while ( ( mNextEvent = mNextEvent->getNextEvent() ) != NULL )
292    {
293        if ( mNextEvent->isEnabled() )
294        {
295            // Valid Event.
296            return true;
297        }
298    }
299
300    // Invalid Event.
301    return false;
302}
303
304//-----------------------------------------------------------------------------
305//
306// Property Methods.
307//
308//-----------------------------------------------------------------------------
309
310//-----------------------------------------------------------------------------
311// 
312// VTrack::getGroup();
313// 
314// Returns the Track's parent group.
315// 
316//-----------------------------------------------------------------------------
317VGroup *VTrack::getGroup( void )
318{
319    return dynamic_cast<VGroup*>( mParentNode );
320}
321
322//-----------------------------------------------------------------------------
323// 
324// VTrack::getNextEvent();
325// 
326// Returns the Event that the Track is currently observing.
327// 
328//-----------------------------------------------------------------------------
329VEvent *VTrack::getNextEvent( void )
330{
331    return mNextEvent;
332}
333
334//-----------------------------------------------------------------------------
335// 
336// VTrack::getCurrentEvent();
337// 
338// Returns the Event that the Track is currently observing and playing. This
339// will only ever be non-null when the track is observing an Event that has a
340// non-zero duration and has been triggered.
341// 
342//-----------------------------------------------------------------------------
343VEvent *VTrack::getCurrentEvent( void )
344{
345    if ( mNextEvent && mNextEvent->isPlaying() )
346    {
347        return mNextEvent;
348    }
349
350    return NULL;
351}
352
353//-----------------------------------------------------------------------------
354// 
355// VTrack::getPreviousEvent();
356// 
357// Returns the Event that the Track was last intergrating.
358// 
359//-----------------------------------------------------------------------------
360VEvent *VTrack::getPreviousEvent( void )
361{
362    if ( mNextEvent )
363    {
364        return mNextEvent->getPreviousEvent();
365    }
366
367    if ( !isControllerPlayingForward() )
368    {
369        return dynamic_cast<VEvent*>( getChild() );
370    }
371
372    return dynamic_cast<VEvent*>( getLastChild() );
373}
374
375//-----------------------------------------------------------------------------
376// 
377// VTrack::calclateInterp( pTime );
378// 
379// This method returns the interp time between or within events. If the given
380// time is between two events, the return time is:
381//
382//     ( pTime - last_event_finish_time )
383//                         / ( next_event_start_time - last_event_finish_time )
384// 
385// If the given time is within an event, the return time is:
386//
387//     ( pTime - event_start_time ) / ( event_duration )
388//
389// The value returned here is between 0.0 and 1.0.
390// 
391//-----------------------------------------------------------------------------
392F32 VTrack::calculateInterp( S32 pTime )
393{
394    if ( !isControllerPlayingForward() )
395    {
396        return ( 1.f - _calculateInterp( pTime ) );
397    }
398
399    return _calculateInterp( pTime );
400}
401
402F32 VTrack::_calculateInterp( S32 pTime )
403{
404    // Fetch Duration.
405    const S32 sequenceDuration = getControllerDuration();
406    if ( sequenceDuration == 0 || pTime == sequenceDuration )
407    {
408        // Sanity!
409        return 1.f;
410    }
411
412    if ( !mChildNode )
413    {
414        // Quick Interp.
415        return F32( pTime / sequenceDuration );
416    }
417
418    // Last Time.
419    S32 lastTime = 0;
420
421    VEvent *walk = ( VEvent* )mChildNode;
422    while ( walk )
423    {
424        const S32 startTime  = walk->getStartTime();
425        const S32 finishTime = walk->getFinishTime();
426
427        if ( pTime < startTime )
428        {
429            return ( F32( pTime - lastTime ) / F32( startTime - lastTime ) );
430        }
431
432        // Update Last Time.
433        lastTime = startTime;
434
435        if ( pTime < finishTime )
436        {
437            return ( F32( pTime - lastTime ) / F32( finishTime - lastTime ) );
438        }
439
440        // Update Last Time.
441        lastTime = finishTime;
442
443        // Fetch Next Node.
444        walk = ( VEvent* )walk->mSiblingNextNode;
445    }
446
447    // Return.
448    return ( F32( pTime - lastTime ) / F32( sequenceDuration - lastTime ) );
449}
450