BL_ShapeActionActuator::BL_ShapeActionActuator(SCA_IObject* gameobj, const STR_String& propname, const STR_String& framepropname, float starttime, float endtime, struct bAction *action, short playtype, short blendin, short priority, float stride) : SCA_IActuator(gameobj, KX_ACT_SHAPEACTION), m_lastpos(0, 0, 0), m_blendframe(0), m_flag(0), m_startframe (starttime), m_endframe(endtime) , m_starttime(0), m_localtime(starttime), m_lastUpdate(-1), m_blendin(blendin), m_blendstart(0), m_stridelength(stride), m_playtype(playtype), m_priority(priority), m_action(action), m_framepropname(framepropname), m_propname(propname) { m_idptr = new PointerRNA(); BL_DeformableGameObject *obj = (BL_DeformableGameObject*)GetParent(); BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); RNA_id_pointer_create(&shape_deformer->GetKey()->id, m_idptr); };
BL_Action::BL_Action(class KX_GameObject* gameobj) : m_action(NULL), m_pose(NULL), m_blendpose(NULL), m_blendinpose(NULL), m_ptrrna(NULL), m_obj(gameobj), m_startframe(0.f), m_endframe(0.f), m_endtime(0.f), m_localtime(0.f), m_blendin(0.f), m_blendframe(0.f), m_blendstart(0.f), m_speed(0.f), m_priority(0), m_playmode(0), m_ipo_flags(0), m_done(true), m_calc_localtime(true) { if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) { BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; m_ptrrna = new PointerRNA(); RNA_id_pointer_create(&obj->GetArmatureObject()->id, m_ptrrna); } else { BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); if (shape_deformer) { m_ptrrna = new PointerRNA(); RNA_id_pointer_create(&shape_deformer->GetKey()->id, m_ptrrna); } } }
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); } }
bool BL_Action::Play(const char* name, float start, float end, short priority, float blendin, short play_mode, float layer_weight, short ipo_flags, float playback_speed) { // Only start playing a new action if we're done, or if // the new action has a higher priority if (!IsDone() && priority > m_priority) return false; m_priority = priority; bAction* prev_action = m_action; // First try to load the action m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name); if (!m_action) { printf("Failed to load action: %s\n", name); m_done = true; return false; } // If we have the same settings, don't play again // This is to resolve potential issues with pulses on sensors such as the ones // reported in bug #29412. The fix is here so it works for both logic bricks and Python. // However, this may eventually lead to issues where a user wants to override an already // playing action with the same action and settings. If this becomes an issue, // then this fix may have to be re-evaluated. if (!IsDone() && m_action == prev_action && m_startframe == start && m_endframe == end && m_priority == priority && m_speed == playback_speed) return false; if (prev_action != m_action) { // First get rid of any old controllers ClearControllerList(); // Create an SG_Controller SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); // Extra controllers if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT) { sg_contr = BL_CreateLampIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); } else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA) { sg_contr = BL_CreateCameraIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); } } m_ipo_flags = ipo_flags; InitIPO(); // Setup blendin shapes/poses if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) { BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; obj->GetMRDPose(&m_blendinpose); } else { BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); if (shape_deformer && shape_deformer->GetKey()) { obj->GetShape(m_blendinshape); // Now that we have the previous blend shape saved, we can clear out the key to avoid any // further interference. KeyBlock *kb; for (kb=(KeyBlock*)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock*)kb->next) kb->curval = 0.f; } } // Now that we have an action, we have something we can play m_starttime = -1.f; // We get the start time on our first update m_startframe = m_localtime = start; m_endframe = end; m_blendin = blendin; m_playmode = play_mode; m_endtime = 0.f; m_blendframe = 0.f; m_blendstart = 0.f; m_speed = playback_speed; m_layer_weight = layer_weight; m_done = false; return true; }
bool BL_Action::Play(const char* name, float start, float end, short priority, float blendin, short play_mode, float layer_weight, short ipo_flags, float playback_speed) { // Only start playing a new action if we're done, or if // the new action has a higher priority if (priority != 0 && !IsDone() && priority >= m_priority) return false; m_priority = priority; bAction* prev_action = m_action; // First try to load the action m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name); if (!m_action) { printf("Failed to load action: %s\n", name); m_done = true; return false; } if (prev_action != m_action) { // First get rid of any old controllers ClearControllerList(); // Create an SG_Controller SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); // Extra controllers if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT) { sg_contr = BL_CreateLampIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); } else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA) { sg_contr = BL_CreateCameraIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); } } m_ipo_flags = ipo_flags; InitIPO(); // Setup blendin shapes/poses if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) { BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; obj->GetMRDPose(&m_blendinpose); } else { BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); if (shape_deformer && shape_deformer->GetKey()) { obj->GetShape(m_blendinshape); // Now that we have the previous blend shape saved, we can clear out the key to avoid any // further interference. KeyBlock *kb; for (kb=(KeyBlock*)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock*)kb->next) kb->curval = 0.f; } } // Now that we have an action, we have something we can play m_starttime = KX_GetActiveEngine()->GetFrameTime(); m_startframe = m_localtime = start; m_endframe = end; m_blendin = blendin; m_playmode = play_mode; m_endtime = 0.f; m_blendframe = 0.f; m_blendstart = 0.f; m_speed = playback_speed; m_layer_weight = layer_weight; m_done = false; return true; }
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, 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); } } }
bool BL_Action::Play(const std::string& name, float start, float end, short priority, float blendin, short play_mode, float layer_weight, short ipo_flags, float playback_speed, short blend_mode) { // Only start playing a new action if we're done, or if // the new action has a higher priority if (!IsDone() && priority > m_priority) return false; m_priority = priority; bAction* prev_action = m_action; KX_Scene* kxscene = m_obj->GetScene(); // First try to load the action m_action = (bAction*)kxscene->GetLogicManager()->GetActionByName(name); if (!m_action) { CM_Error("failed to load action: " << name); m_done = true; return false; } // If we have the same settings, don't play again // This is to resolve potential issues with pulses on sensors such as the ones // reported in bug #29412. The fix is here so it works for both logic bricks and Python. // However, this may eventually lead to issues where a user wants to override an already // playing action with the same action and settings. If this becomes an issue, // then this fix may have to be re-evaluated. if (!IsDone() && m_action == prev_action && m_startframe == start && m_endframe == end && m_priority == priority && m_speed == playback_speed) return false; // Keep a copy of the action for threading purposes if (m_tmpaction) { BKE_libblock_free(G.main, m_tmpaction); m_tmpaction = NULL; } m_tmpaction = BKE_action_copy(G.main, m_action); // First get rid of any old controllers ClearControllerList(); // Create an SG_Controller SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, kxscene->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); // World sg_contr = BL_CreateWorldIPO(m_action, kxscene->GetBlenderScene()->world, kxscene->GetSceneConverter()); if (sg_contr) { m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); } // Try obcolor sg_contr = BL_CreateObColorIPO(m_action, m_obj, kxscene->GetSceneConverter()); if (sg_contr) { m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); } // Now try materials for (int matidx = 1; matidx <= m_obj->GetBlenderObject()->totcol; ++matidx) { Material *mat = give_current_material(m_obj->GetBlenderObject(), matidx); if (!mat) { continue; } KX_BlenderSceneConverter *converter = kxscene->GetSceneConverter(); RAS_IPolyMaterial *polymat = converter->FindCachedPolyMaterial(kxscene, mat); if (!polymat) { continue; } sg_contr = BL_CreateMaterialIpo(m_action, mat, polymat, m_obj, converter); if (sg_contr) { m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); } } // Extra controllers if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT) { sg_contr = BL_CreateLampIPO(m_action, m_obj, kxscene->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); } else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA) { sg_contr = BL_CreateCameraIPO(m_action, m_obj, kxscene->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); } m_ipo_flags = ipo_flags; InitIPO(); // Setup blendin shapes/poses if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) { BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; obj->GetPose(&m_blendinpose); } else { BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); if (shape_deformer && shape_deformer->GetKey()) { obj->GetShape(m_blendinshape); // Now that we have the previous blend shape saved, we can clear out the key to avoid any // further interference. KeyBlock *kb; for (kb=(KeyBlock *)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock *)kb->next) kb->curval = 0.f; } } // Now that we have an action, we have something we can play m_starttime = KX_GetActiveEngine()->GetFrameTime() - kxscene->getSuspendedDelta(); m_startframe = m_localframe = start; m_endframe = end; m_blendin = blendin; m_playmode = play_mode; m_blendmode = blend_mode; m_blendframe = 0.f; m_blendstart = 0.f; m_speed = playback_speed; m_layer_weight = layer_weight; m_done = false; m_appliedToObject = false; m_prevUpdate = -1.0f; return true; }