bool BL_ShapeActionActuator::Update(double curtime, bool frame) { bool bNegativeEvent = false; bool bPositiveEvent = false; bool keepgoing = true; bool wrap = false; bool apply=true; int priority; float newweight; curtime -= KX_KetsjiEngine::GetSuspendedDelta(); // result = true if animation has to be continued, false if animation stops // maybe there are events for us in the queue ! if (frame) { bNegativeEvent = m_negevent; bPositiveEvent = m_posevent; RemoveAllEvents(); if (bPositiveEvent) m_flag |= ACT_FLAG_ACTIVE; if (bNegativeEvent) { if (!(m_flag & ACT_FLAG_ACTIVE)) return false; m_flag &= ~ACT_FLAG_ACTIVE; } } /* This action can only be attached to a deform object */ BL_DeformableGameObject *obj = (BL_DeformableGameObject*)GetParent(); float length = m_endframe - m_startframe; priority = m_priority; /* Determine pre-incrementation behaviour and set appropriate flags */ switch (m_playtype){ case ACT_ACTION_MOTION: if (bNegativeEvent){ keepgoing=false; apply=false; }; break; case ACT_ACTION_FROM_PROP: if (bNegativeEvent){ apply=false; keepgoing=false; } break; case ACT_ACTION_LOOP_END: if (bPositiveEvent){ if (!(m_flag & ACT_FLAG_LOCKINPUT)){ m_flag &= ~ACT_FLAG_KEYUP; m_flag &= ~ACT_FLAG_REVERSE; m_flag |= ACT_FLAG_LOCKINPUT; m_localtime = m_startframe; m_starttime = curtime; } } if (bNegativeEvent){ m_flag |= ACT_FLAG_KEYUP; } break; case ACT_ACTION_LOOP_STOP: if (bPositiveEvent){ if (!(m_flag & ACT_FLAG_LOCKINPUT)){ m_flag &= ~ACT_FLAG_REVERSE; m_flag &= ~ACT_FLAG_KEYUP; m_flag |= ACT_FLAG_LOCKINPUT; SetStartTime(curtime); } } if (bNegativeEvent){ m_flag |= ACT_FLAG_KEYUP; m_flag &= ~ACT_FLAG_LOCKINPUT; keepgoing=false; apply=false; } break; case ACT_ACTION_PINGPONG: if (bPositiveEvent){ if (!(m_flag & ACT_FLAG_LOCKINPUT)){ m_flag &= ~ACT_FLAG_KEYUP; m_localtime = m_starttime; m_starttime = curtime; m_flag |= ACT_FLAG_LOCKINPUT; } } break; case ACT_ACTION_FLIPPER: if (bPositiveEvent){ if (!(m_flag & ACT_FLAG_LOCKINPUT)){ m_flag &= ~ACT_FLAG_REVERSE; m_flag |= ACT_FLAG_LOCKINPUT; SetStartTime(curtime); } } else if (bNegativeEvent){ m_flag |= ACT_FLAG_REVERSE; m_flag &= ~ACT_FLAG_LOCKINPUT; SetStartTime(curtime); } break; case ACT_ACTION_PLAY: if (bPositiveEvent){ if (!(m_flag & ACT_FLAG_LOCKINPUT)){ m_flag &= ~ACT_FLAG_REVERSE; m_localtime = m_starttime; m_starttime = curtime; m_flag |= ACT_FLAG_LOCKINPUT; } } break; default: break; } /* Perform increment */ if (keepgoing){ if (m_playtype == ACT_ACTION_MOTION){ MT_Point3 newpos; MT_Point3 deltapos; newpos = obj->NodeGetWorldPosition(); /* Find displacement */ deltapos = newpos-m_lastpos; m_localtime += (length/m_stridelength) * deltapos.length(); m_lastpos = newpos; } else{ SetLocalTime(curtime); } } /* Check if a wrapping response is needed */ if (length){ if (m_localtime < m_startframe || m_localtime > m_endframe) { m_localtime = m_startframe + fmod(m_localtime, length); wrap = true; } } else m_localtime = m_startframe; /* Perform post-increment tasks */ switch (m_playtype){ case ACT_ACTION_FROM_PROP: { CValue* propval = GetParent()->GetProperty(m_propname); if (propval) m_localtime = propval->GetNumber(); if (bNegativeEvent){ keepgoing=false; } } break; case ACT_ACTION_MOTION: break; case ACT_ACTION_LOOP_STOP: break; case ACT_ACTION_PINGPONG: if (wrap){ if (!(m_flag & ACT_FLAG_REVERSE)) m_localtime = m_endframe; else m_localtime = m_startframe; m_flag &= ~ACT_FLAG_LOCKINPUT; m_flag ^= ACT_FLAG_REVERSE; //flip direction keepgoing = false; } break; case ACT_ACTION_FLIPPER: if (wrap){ if (!(m_flag & ACT_FLAG_REVERSE)){ m_localtime=m_endframe; //keepgoing = false; } else { m_localtime=m_startframe; keepgoing = false; } } break; case ACT_ACTION_LOOP_END: if (wrap){ if (m_flag & ACT_FLAG_KEYUP){ keepgoing = false; m_localtime = m_endframe; m_flag &= ~ACT_FLAG_LOCKINPUT; } SetStartTime(curtime); } break; case ACT_ACTION_PLAY: if (wrap){ m_localtime = m_endframe; keepgoing = false; m_flag &= ~ACT_FLAG_LOCKINPUT; } break; default: keepgoing = false; break; } /* Set the property if its defined */ if (m_framepropname[0] != '\0') { CValue* propowner = GetParent(); CValue* oldprop = propowner->GetProperty(m_framepropname); CValue* newval = new CFloatValue(m_localtime); if (oldprop) { oldprop->SetValue(newval); } else { propowner->SetProperty(m_framepropname, newval); } newval->Release(); } if (bNegativeEvent) m_blendframe=0.0f; /* Apply the pose if necessary*/ if (apply) { /* Priority test */ if (obj->SetActiveAction(this, priority, curtime)){ BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); Key *key = NULL; if (shape_deformer) key = shape_deformer->GetKey(); if (!key) { // this could happen if the mesh was changed in the middle of an action // and the new mesh has no key, stop the action keepgoing = false; } else { ListBase tchanbase= {NULL, NULL}; if (m_blendin && m_blendframe==0.0f){ // this is the start of the blending, remember the startup shape obj->GetShape(m_blendshape); m_blendstart = curtime; } KeyBlock *kb; // We go through and clear out the keyblocks so there isn't any interference // from other shape actions for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next) kb->curval = 0.f; animsys_evaluate_action(m_idptr, m_action, NULL, m_localtime); // XXX - in 2.5 theres no way to do this. possibly not that important to support - Campbell if (0) { // XXX !execute_ipochannels(&tchanbase)) { // no update, this is possible if action does not match the keys, stop the action keepgoing = false; } else { // the key have changed, apply blending if needed if (m_blendin && (m_blendframe<m_blendin)){ newweight = (m_blendframe/(float)m_blendin); BlendShape(key, 1.0f - newweight); /* Increment current blending percentage */ m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate(); if (m_blendframe>m_blendin) m_blendframe = m_blendin; } m_lastUpdate = m_localtime; } BLI_freelistN(&tchanbase); } } else{ m_blendframe = 0.0f; } } if (!keepgoing){ m_blendframe = 0.0f; } return keepgoing; };
void BL_Action::Update(float curtime) { // Don't bother if we're done with the animation if (m_done) return; curtime -= KX_KetsjiEngine::GetSuspendedDelta(); // Grab the start time here so we don't end up with a negative m_localtime when // suspending and resuming scenes. if (m_starttime < 0) m_starttime = curtime; if (m_calc_localtime) SetLocalTime(curtime); else { ResetStartTime(curtime); m_calc_localtime = true; } // Handle wrap around if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe)) { switch (m_playmode) { case ACT_MODE_PLAY: // Clamp m_localtime = m_endframe; m_done = true; break; case ACT_MODE_LOOP: // Put the time back to the beginning m_localtime = m_startframe; m_starttime = curtime; break; case ACT_MODE_PING_PONG: // Swap the start and end frames float temp = m_startframe; m_startframe = m_endframe; m_endframe = temp; m_starttime = curtime; break; } } if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) { BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; obj->GetPose(&m_pose); // Extract the pose from the action { Object *arm = obj->GetArmatureObject(); bPose *temp = arm->pose; arm->pose = m_pose; animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime); arm->pose = temp; } // Handle blending between armature actions if (m_blendin && m_blendframe<m_blendin) { IncrementBlending(curtime); // Calculate weight float weight = 1.f - (m_blendframe/m_blendin); // Blend the poses game_blend_poses(m_pose, m_blendinpose, weight); } // Handle layer blending if (m_layer_weight >= 0) { obj->GetMRDPose(&m_blendpose); game_blend_poses(m_pose, m_blendpose, m_layer_weight); } obj->SetPose(m_pose); obj->SetActiveAction(NULL, 0, curtime); } else { BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); // Handle shape actions if we have any if (shape_deformer && shape_deformer->GetKey()) { Key *key = shape_deformer->GetKey(); animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime); // Handle blending between shape actions if (m_blendin && m_blendframe < m_blendin) { IncrementBlending(curtime); float weight = 1.f - (m_blendframe/m_blendin); // We go through and clear out the keyblocks so there isn't any interference // from other shape actions KeyBlock *kb; for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next) kb->curval = 0.f; // Now blend the shape BlendShape(key, weight, m_blendinshape); } // Handle layer blending if (m_layer_weight >= 0) { obj->GetShape(m_blendshape); BlendShape(key, m_layer_weight, m_blendshape); } obj->SetActiveAction(NULL, 0, curtime); } m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD); } }
void BL_Action::Update(float curtime, bool applyToObject) { /* Don't bother if we're done with the animation and if the animation was already applied to the object. * of if the animation made a double update for the same time and that it was applied to the object. */ if ((m_done && m_appliedToObject) || (m_prevUpdate == curtime && m_appliedToObject)) { return; } m_prevUpdate = curtime; curtime -= (float)KX_KetsjiEngine::GetSuspendedDelta(); if (m_calc_localtime) SetLocalTime(curtime); else { ResetStartTime(curtime); m_calc_localtime = true; } // Handle wrap around if (m_localframe < std::min(m_startframe, m_endframe) || m_localframe > std::max(m_startframe, m_endframe)) { switch (m_playmode) { case ACT_MODE_PLAY: // Clamp m_localframe = m_endframe; m_done = true; break; case ACT_MODE_LOOP: // Put the time back to the beginning m_localframe = m_startframe; m_starttime = curtime; break; case ACT_MODE_PING_PONG: // Swap the start and end frames float temp = m_startframe; m_startframe = m_endframe; m_endframe = temp; m_starttime = curtime; break; } } m_appliedToObject = applyToObject; // In case of culled armatures (doesn't requesting to transform the object) we only manages time. if (!applyToObject) { return; } if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) { BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; if (m_layer_weight >= 0) obj->GetPose(&m_blendpose); // Extract the pose from the action obj->SetPoseByAction(m_tmpaction, m_localframe); // Handle blending between armature actions if (m_blendin && m_blendframe<m_blendin) { IncrementBlending(curtime); // Calculate weight float weight = 1.f - (m_blendframe/m_blendin); // Blend the poses obj->BlendInPose(m_blendinpose, weight, ACT_BLEND_BLEND); } // Handle layer blending if (m_layer_weight >= 0) obj->BlendInPose(m_blendpose, m_layer_weight, m_blendmode); obj->UpdateTimestep(curtime); } else { BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); // Handle shape actions if we have any if (shape_deformer && shape_deformer->GetKey()) { Key *key = shape_deformer->GetKey(); PointerRNA ptrrna; RNA_id_pointer_create(&key->id, &ptrrna); animsys_evaluate_action(&ptrrna, m_tmpaction, NULL, m_localframe); // Handle blending between shape actions if (m_blendin && m_blendframe < m_blendin) { IncrementBlending(curtime); float weight = 1.f - (m_blendframe/m_blendin); // We go through and clear out the keyblocks so there isn't any interference // from other shape actions KeyBlock *kb; for (kb=(KeyBlock *)key->block.first; kb; kb=(KeyBlock *)kb->next) kb->curval = 0.f; // Now blend the shape BlendShape(key, weight, m_blendinshape); } // Handle layer blending if (m_layer_weight >= 0) { obj->GetShape(m_blendshape); BlendShape(key, m_layer_weight, m_blendshape); } obj->SetActiveAction(0, curtime); } } }