BGE animations: This is an attempt to help smooth out some more compatibility issues with the new action actuator. It now has a similar pulse behavior to the old actuator. This has worked well in most of my tests, but YoFrankie still has problems, and it appears to have gotten a little worse.

This commit is contained in:
Mitchell Stokes 2011-09-01 21:47:46 +00:00
parent 0f2be67bbf
commit 99d5fa70de
2 changed files with 87 additions and 27 deletions

@ -129,6 +129,50 @@ void BL_ActionActuator::SetBlendTime (float newtime){
m_blendframe = newtime; m_blendframe = newtime;
} }
void BL_ActionActuator::SetLocalTime(float curtime)
{
float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate();
if (m_endframe < m_startframe)
dt = -dt;
m_localtime = m_startframe + dt;
// Handle wrap around
if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe))
{
switch(m_playtype)
{
case ACT_ACTION_PLAY:
// Clamp
m_localtime = m_endframe;
break;
case ACT_ACTION_LOOP_END:
// Put the time back to the beginning
m_localtime = m_startframe;
m_starttime = curtime;
break;
case ACT_ACTION_PINGPONG:
// Swap the start and end frames
float temp = m_startframe;
m_startframe = m_endframe;
m_endframe = temp;
m_starttime = curtime;
break;
}
}
}
void BL_ActionActuator::ResetStartTime(float curtime)
{
float dt = m_localtime - m_startframe;
m_starttime = curtime - dt / (KX_KetsjiEngine::GetAnimFrameRate());
//SetLocalTime(curtime);
}
CValue* BL_ActionActuator::GetReplica() { CValue* BL_ActionActuator::GetReplica() {
BL_ActionActuator* replica = new BL_ActionActuator(*this);//m_float,GetName()); BL_ActionActuator* replica = new BL_ActionActuator(*this);//m_float,GetName());
replica->ProcessReplica(); replica->ProcessReplica();
@ -194,11 +238,46 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
RemoveAllEvents(); RemoveAllEvents();
} }
if (bUseContinue && (m_flag & ACT_FLAG_ACTIVE)) if (m_flag & ACT_FLAG_ATTEMPT_PLAY)
m_localtime = obj->GetActionFrame(m_layer); SetLocalTime(curtime);
if (bPositiveEvent) if (bUseContinue && (m_flag & ACT_FLAG_ACTIVE))
{ {
m_localtime = obj->GetActionFrame(m_layer);
ResetStartTime(curtime);
}
// Handle a frame property if it's defined
if ((m_flag & ACT_FLAG_ACTIVE) && m_framepropname[0] != 0)
{
CValue* oldprop = obj->GetProperty(m_framepropname);
CValue* newval = new CFloatValue(obj->GetActionFrame(m_layer));
if (oldprop)
oldprop->SetValue(newval);
else
obj->SetProperty(m_framepropname, newval);
newval->Release();
}
// Handle a finished animation
if ((m_flag & ACT_FLAG_PLAY_END) && obj->IsActionDone(m_layer))
{
m_flag &= ~ACT_FLAG_ACTIVE;
m_flag &= ~ACT_FLAG_ATTEMPT_PLAY;
obj->StopAction(m_layer);
return false;
}
// If a different action is playing, we've been overruled and are no longer active
if (obj->GetCurrentAction(m_layer) != m_action)
m_flag &= ~ACT_FLAG_ACTIVE;
if (bPositiveEvent || (m_flag & ACT_FLAG_ATTEMPT_PLAY && !(m_flag & ACT_FLAG_ACTIVE)))
{
if (bPositiveEvent)
ResetStartTime(curtime);
if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, playtype, m_layer_weight, m_ipo_flags)) if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, playtype, m_layer_weight, m_ipo_flags))
{ {
m_flag |= ACT_FLAG_ACTIVE; m_flag |= ACT_FLAG_ACTIVE;
@ -210,11 +289,11 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
else else
m_flag &= ~ACT_FLAG_PLAY_END; m_flag &= ~ACT_FLAG_PLAY_END;
} }
else m_flag |= ACT_FLAG_ATTEMPT_PLAY;
return false;
} }
else if ((m_flag & ACT_FLAG_ACTIVE) && bNegativeEvent) else if ((m_flag & ACT_FLAG_ACTIVE) && bNegativeEvent)
{ {
m_flag &= ~ACT_FLAG_ATTEMPT_PLAY;
bAction *curr_action = obj->GetCurrentAction(m_layer); bAction *curr_action = obj->GetCurrentAction(m_layer);
if (curr_action && curr_action != m_action) if (curr_action && curr_action != m_action)
{ {
@ -259,27 +338,6 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
} }
} }
// Handle a frame property if it's defined
if ((m_flag & ACT_FLAG_ACTIVE) && m_framepropname[0] != 0)
{
CValue* oldprop = obj->GetProperty(m_framepropname);
CValue* newval = new CFloatValue(obj->GetActionFrame(m_layer));
if (oldprop)
oldprop->SetValue(newval);
else
obj->SetProperty(m_framepropname, newval);
newval->Release();
}
// Handle a finished animation
if ((m_flag & ACT_FLAG_PLAY_END) && obj->IsActionDone(m_layer))
{
m_flag &= ~ACT_FLAG_ACTIVE;
obj->StopAction(m_layer);
return false;
}
return true; return true;
} }

@ -64,6 +64,8 @@ public:
virtual void ProcessReplica(); virtual void ProcessReplica();
void SetBlendTime (float newtime); void SetBlendTime (float newtime);
void SetLocalTime (float curtime);
void ResetStartTime (float curtime);
bAction* GetAction() { return m_action; } bAction* GetAction() { return m_action; }
void SetAction(bAction* act) { m_action= act; } void SetAction(bAction* act) { m_action= act; }
@ -150,7 +152,7 @@ enum {
ACT_FLAG_ACTIVE = 1<<3, ACT_FLAG_ACTIVE = 1<<3,
ACT_FLAG_CONTINUE = 1<<4, ACT_FLAG_CONTINUE = 1<<4,
ACT_FLAG_PLAY_END = 1<<5, ACT_FLAG_PLAY_END = 1<<5,
ACT_FLAG_ATTEMPT_PLAY = 1<<6,
}; };
#endif #endif