The-Simpsons-Hit-and-Run/game/code/ai/sequencer/sequencer.cpp

316 lines
6.9 KiB
C++

//-----------------------------------------------------------------------------
// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
//
// sequencer.cpp
//
// Description: This class queues the actions of an actor.
// The sequencer places actions into multiple queues,
// named tracks, which can be grouped into larger composite
// actions named sequences, which will be executed in turn.
//
// Modification History:
// + Created Aug 14, 2001 -- Gary Keong
// - Snapshot from Hair Club (rev 3) Owner: Bryan Brandt
//-----------------------------------------------------------------------------
#include <raddebug.hpp>
#include <ai\sequencer\sequencer.h>
#include <ai\sequencer\action.h>
static bool s_StopClear = false;
//---------------------------------------------------------------------
// Sequencer class
//---------------------------------------------------------------------
Sequencer::Sequencer():
m_SequenceCount(0),
m_State(STATE_NONE),
m_TimeElapsed(0.0f)
{
}
Sequencer::~Sequencer()
{
Clear();
}
void Sequencer::ClearSequence(sSequence* seq)
{
sAction* curAction = seq->actions;
// iterate over all actions of current sequence
for (unsigned i = 0; i < seq->actionCount; ++i)
{
if ( curAction->action )
{
if ( curAction->action->IsRunning() )
{
curAction->action->Clear();
}
// [Dusit: June 14th, 2003]
// always gets called to abort safely whether
// the action's running or not.
curAction->action->Abort();
}
tRefCounted::Release( curAction->action );
curAction->action = 0;
++curAction;
}
seq->actionCount = 0;
}
void Sequencer::Clear()
{
rAssert(!s_StopClear);
// empty all sequences
for (unsigned i = 0; i < m_SequenceCount; ++i)
{
ClearSequence(m_Sequences + i);
}
m_SequenceCount = 0;
m_State = STATE_NONE;
m_TimeElapsed = 0.0f;
}
void Sequencer::BeginSequence()
{
rAssert(m_State == STATE_NONE);
rAssert(m_SequenceCount < MAX_SEQUENCES);
// add new sequence, set current sequence index to it,
// and reset current track to zero
m_pCurrentSequence = (m_Sequences + m_SequenceCount);
++m_SequenceCount;
// reset current sequence
m_pCurrentSequence->actionCount = 0;
// indicate we can now add tracks/timed actions
m_State = STATE_SEQUENCE;
}
void Sequencer::EndSequence()
{
rAssert(m_State == STATE_SEQUENCE);
m_State = STATE_NONE;
}
void Sequencer::AddAction(float t_begin, float t_duration, Action* action)
{
// we need a sequence to add an action
rAssert(m_State != STATE_NONE);
rAssert(action != 0);
// allocate a new track for the action
sAction* curAction = (m_pCurrentSequence->actions + m_pCurrentSequence->actionCount);
++(m_pCurrentSequence->actionCount);
// action runs from t_begin for t_duration seconds
curAction->timeBegin = t_begin;
curAction->timeDuration = t_duration;
curAction->action = action;
curAction->action->AddRef( );
}
void Sequencer::AddActionToSequence(float t_begin, float t_duration, Action* action)
{
// we assume a sequence already exists
rAssert(m_State == STATE_NONE);
rAssert(m_SequenceCount > 0);
rAssert(action != 0);
// allocate a new track for the action
sAction* curAction = (m_pCurrentSequence->actions + m_pCurrentSequence->actionCount);
++(m_pCurrentSequence->actionCount);
// we need to offset our times from NOW
curAction->timeBegin = (m_TimeElapsed + t_begin);
curAction->timeDuration = t_duration;
curAction->action = action;
curAction->action->AddRef( );
}
bool Sequencer::IsBusy() const
{
if (m_SequenceCount <= 0)
return false;
unsigned actionIdx = 0;
const sAction* curAction = m_Sequences->actions;
// iterate over all tracks of current sequence
while (actionIdx < m_Sequences->actionCount)
{
// is track active?
if (curAction->action != 0)
return true;
++actionIdx;
++curAction;
}
// no tracks had actions in queue
return false;
}
void Sequencer::WakeUp(float time)
{
if (m_SequenceCount <= 0)
return;
// CLOSER??? m_TimeElapsed += SIMULATION_TIME;
m_TimeElapsed += time;
unsigned actionIdx = 0;
sAction* curAction = m_Sequences->actions;
// iterate over all tracks of current sequence
while (actionIdx < m_Sequences->actionCount)
{
// is track active?
if (curAction->action != 0)
{
// check to see if action should be running yet
if (curAction->timeBegin <= m_TimeElapsed)
{
Action* action = curAction->action;
// Is the current action sleeping?
if (action->IsSleeping())
{
// Wake-up the action.
action->WakeUp(time);
// Start the action only if wakeup didn't kill it
if (!action->IsDone())
{
action->Run();
}
}
}
}
++actionIdx;
++curAction;
}
}
void Sequencer::DoSimulation(float time)
{
if (m_SequenceCount <= 0)
return;
unsigned actionIdx = 0;
sAction* curAction = m_Sequences->actions;
// iterate over all tracks of current sequence
while (actionIdx < m_Sequences->actionCount)
{
// is track active?
if (curAction->action != 0)
{
// check to see if action should be running yet
if (curAction->timeBegin <= m_TimeElapsed)
{
Action* action = curAction->action;
// Is the current action running? Yes, then do a simulation.
if (action->IsRunning())
{
action->DoSimulation(time);
}
// if action is non-indefinite, age it
if (curAction->timeDuration >= 0.0f)
{
// age the action
curAction->timeDuration -= time;
// if the action time has elapsed, finish it
if (curAction->timeDuration <= 0.0f)
{
action->Done();
}
}
}
}
++actionIdx;
++curAction;
}
}
void Sequencer::Update(float time)
{
if (m_SequenceCount <= 0)
return;
unsigned masterCount = 0;
unsigned actionIdx = 0;
sAction* curAction = m_Sequences->actions;
// iterate over all tracks
while (actionIdx < m_Sequences->actionCount)
{
Action* action = curAction->action;
// does track have an action?
if (action != 0)
{
// Is the current action running? Yes, then get the new status.
if (action->IsRunning())
{
s_StopClear = true;
action->Update(time);
s_StopClear = false;
}
// Is the current action done or failed?
// Yes, then clear action
if (action->IsDone())
{
action->Clear();
action->Release( );
curAction->action = 0;
}
else
{
// accumulate master action count
if (!action->IsSlave())
{
++masterCount;
}
}
}
++actionIdx;
++curAction;
}
if (masterCount <= 0)
{
// we have no master actions, so move on to
// the next sequence
ClearSequence(m_Sequences);
for (unsigned i = 1; i < m_SequenceCount; ++i)
{
m_Sequences[i-1] = m_Sequences[i];
}
if(m_SequenceCount)
{
--(m_SequenceCount);
}
// reset time origin for next sequence
m_TimeElapsed = 0.0f;
}
}
// End of file.