BL_Action::~BL_Action() { if (m_pose) game_free_pose(m_pose); if (m_blendpose) game_free_pose(m_blendpose); if (m_blendinpose) game_free_pose(m_blendinpose); ClearControllerList(); }
void BL_Action::UpdateIPOs() { /* This function does nothing if the scene graph controllers are already removed * by ClearControllerList. */ m_obj->UpdateIPO(m_localframe, m_ipo_flags & ACT_IPOFLAG_CHILD); // If the action is done we can remove its scene graph IPO controller. if (m_done) { ClearControllerList(); } }
BL_Action::~BL_Action() { if (m_blendpose) BKE_pose_free(m_blendpose); if (m_blendinpose) BKE_pose_free(m_blendinpose); ClearControllerList(); if (m_tmpaction) { BKE_libblock_free(G.main, m_tmpaction); m_tmpaction = NULL; } }
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_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; }
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; PointerRNA ptrrna; RNA_id_pointer_create(&arm->id, &ptrrna); animsys_evaluate_action(&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(); PointerRNA ptrrna; RNA_id_pointer_create(&key->id, &ptrrna); animsys_evaluate_action(&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); } if (m_done) ClearControllerList(); }