iTickable.cpp

Engine/source/core/iTickable.cpp

More...

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  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
 24#include "core/iTickable.h"
 25
 26// The statics
 27U32 ITickable::smLastTick = 0;
 28U32 ITickable::smLastTime = 0;
 29U32 ITickable::smLastDelta = 0;
 30
 31U32 ITickable::smTickShift = 5;
 32U32 ITickable::smTickMs = ( 1 << smTickShift );
 33F32 ITickable::smTickSec = ( F32( ITickable::smTickMs ) / 1000.f );
 34U32 ITickable::smTickMask = ( smTickMs - 1 );
 35
 36//------------------------------------------------------------------------------
 37
 38ITickable::ITickable() : mProcessTick( true )
 39{
 40   getProcessList().push_back( this );
 41}
 42
 43//------------------------------------------------------------------------------
 44
 45ITickable::~ITickable()
 46{
 47   for( ProcessListIterator i = getProcessList().begin(); i != getProcessList().end(); i++ )
 48   {
 49      if( (*i) == this )
 50      {
 51         getProcessList().erase( i );
 52         return;
 53      }
 54   }
 55}
 56
 57//------------------------------------------------------------------------------
 58
 59void ITickable::init( const U32 tickShift )
 60{
 61    // Sanity!
 62    AssertFatal( tickShift == 0 || tickShift <= 31, "ITickable::init() - Invalid 'tickShift' parameter!" );
 63
 64    // Calculate tick constants.
 65    smTickShift = tickShift;
 66    smTickMs = ( 1 << smTickShift );
 67    smTickSec = ( F32( smTickMs ) / 1000.f );
 68    smTickMask = ( smTickMs - 1 );
 69}
 70
 71//------------------------------------------------------------------------------
 72
 73Vector<ITickable*>& ITickable::getProcessList()
 74{
 75   // This helps to avoid the static initialization order fiasco
 76   static Vector<ITickable*> smProcessList( __FILE__, __LINE__ ); ///< List of tick controls
 77   return smProcessList;
 78}
 79
 80//------------------------------------------------------------------------------
 81
 82bool ITickable::advanceTime( U32 timeDelta )
 83{
 84   U32 targetTime = smLastTime + timeDelta;
 85   U32 targetTick = ( targetTime + smTickMask ) & ~smTickMask;
 86   U32 tickCount = ( targetTick - smLastTick ) >> smTickShift;
 87
 88   // Advance objects
 89   if( tickCount )
 90   {
 91      for( ; smLastTick != targetTick; smLastTick += smTickMs )
 92      {
 93         for( U32 i=0; i < getProcessList().size(); )
 94         {
 95            ITickable* iTick = getProcessList()[i];
 96            if( iTick->isProcessingTicks() )
 97            {
 98               iTick->processTick();
 99
100               // Only advance counter if the tickable hasn't deleted itself
101               if( i < getProcessList().size() && iTick == getProcessList()[i] )
102                  ++i;
103            }
104            else
105            {
106               // Move onto the next tickable
107               ++i;
108            }
109         }
110      }
111   }
112
113   smLastDelta = ( smTickMs - ( targetTime & smTickMask ) ) & smTickMask;
114   F32 dt = smLastDelta / F32( smTickMs );
115
116   // Now interpolate objects that want ticks.  Note that an object should never delete
117   // itself during an interpolateTick().
118   for( ProcessListIterator i = getProcessList().begin(); i != getProcessList().end(); i++ )
119      if( (*i)->isProcessingTicks() )
120         (*i)->interpolateTick( dt );
121
122
123   // Inform ALL objects that time was advanced
124   dt = F32( timeDelta ) / 1000.f;
125   for( U32 i=0; i < getProcessList().size(); )
126   {
127      ITickable* iTick = getProcessList()[i];
128      iTick->advanceTime( dt );
129
130      // Only advance counter if the tickable hasn't deleted itself
131      if( i < getProcessList().size() && iTick == getProcessList()[i] )
132         ++i;
133   }
134
135   smLastTime = targetTime;
136
137   return tickCount != 0;
138}
139