bool KX_KetsjiEngine::NextFrame() { double timestep = 1.0/m_ticrate; double framestep = timestep; // static hidden::Clock sClock; m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true); //float dt = sClock.getTimeMicroseconds() * 0.000001f; //sClock.reset(); if (m_bFixedTime) m_clockTime += timestep; else { // m_clockTime += dt; m_clockTime = m_kxsystem->GetTimeInSeconds(); } double deltatime = m_clockTime - m_frameTime; if (deltatime<0.f) { printf("problem with clock\n"); deltatime = 0.f; m_clockTime = 0.f; m_frameTime = 0.f; } // Compute the number of logic frames to do each update (fixed tic bricks) int frames =int(deltatime*m_ticrate+1e-6); // if (frames>1) // printf("****************************************"); // printf("dt = %f, deltatime = %f, frames = %d\n",dt, deltatime,frames); // if (!frames) // PIL_sleep_ms(1); KX_SceneList::iterator sceneit; if (frames>m_maxPhysicsFrame) { // printf("framedOut: %d\n",frames); m_frameTime+=(frames-m_maxPhysicsFrame)*timestep; frames = m_maxPhysicsFrame; } bool doRender = frames>0; if (frames > m_maxLogicFrame) { framestep = (frames*timestep)/m_maxLogicFrame; frames = m_maxLogicFrame; } while (frames) { m_frameTime += framestep; for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit) // for each scene, call the proceed functions { KX_Scene* scene = *sceneit; /* Suspension holds the physics and logic processing for an * entire scene. Objects can be suspended individually, and * the settings for that preceed the logic and physics * update. */ m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true); m_sceneconverter->resetNoneDynamicObjectToIpo();//this is for none dynamic objects with ipo scene->UpdateObjectActivity(); if (!scene->IsSuspended()) { // if the scene was suspended recalcutlate the delta tu "curtime" m_suspendedtime = scene->getSuspendedTime(); if (scene->getSuspendedTime()!=0.0) scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime()); m_suspendeddelta = scene->getSuspendedDelta(); m_logger->StartLog(tc_network, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_NETWORK); scene->GetNetworkScene()->proceed(m_frameTime); //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); //SG_SetActiveStage(SG_STAGE_NETWORK_UPDATE); //scene->UpdateParents(m_frameTime); m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS1); // set Python hooks for each scene #ifndef DISABLE_PYTHON PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); #endif KX_SetActiveScene(scene); scene->GetPhysicsEnvironment()->endFrame(); // Update scenegraph after physics step. This maps physics calculations // into node positions. //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); //SG_SetActiveStage(SG_STAGE_PHYSICS1_UPDATE); //scene->UpdateParents(m_frameTime); // Process sensors, and controllers m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_CONTROLLER); scene->LogicBeginFrame(m_frameTime); // Scenegraph needs to be updated again, because Logic Controllers // can affect the local matrices. m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_CONTROLLER_UPDATE); scene->UpdateParents(m_frameTime); // Process actuators // Do some cleanup work for this logic frame m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_ACTUATOR); scene->LogicUpdateFrame(m_frameTime, true); scene->LogicEndFrame(); // Actuators can affect the scenegraph m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_ACTUATOR_UPDATE); scene->UpdateParents(m_frameTime); m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS2); scene->GetPhysicsEnvironment()->beginFrame(); // Perform physics calculations on the scene. This can involve // many iterations of the physics solver. scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,timestep,framestep);//m_deltatimerealDeltaTime); m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS2_UPDATE); scene->UpdateParents(m_frameTime); if (m_game2ipo) { m_sceneconverter->WritePhysicsObjectToAnimationIpo(++m_currentFrame); } scene->setSuspendedTime(0.0); } // suspended else if(scene->getSuspendedTime()==0.0) scene->setSuspendedTime(m_clockTime); DoSound(scene); m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true); } // update system devices m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true); if (m_keyboarddevice) m_keyboarddevice->NextFrame(); if (m_mousedevice) m_mousedevice->NextFrame(); if (m_networkdevice) m_networkdevice->NextFrame(); // scene management ProcessScheduledScenes(); frames--; } bool bUseAsyncLogicBricks= false;//true; if (bUseAsyncLogicBricks) { // Logic update sub frame: this will let some logic bricks run at the // full frame rate. for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit) // for each scene, call the proceed functions { KX_Scene* scene = *sceneit; if (!scene->IsSuspended()) { // if the scene was suspended recalcutlate the delta tu "curtime" m_suspendedtime = scene->getSuspendedTime(); if (scene->getSuspendedTime()!=0.0) scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime()); m_suspendeddelta = scene->getSuspendedDelta(); // set Python hooks for each scene #ifndef DISABLE_PYTHON PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); #endif KX_SetActiveScene(scene); m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS1); scene->UpdateParents(m_clockTime); // Perform physics calculations on the scene. This can involve // many iterations of the physics solver. m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,timestep,timestep); // Update scenegraph after physics step. This maps physics calculations // into node positions. m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS2); scene->UpdateParents(m_clockTime); // Do some cleanup work for this logic frame m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true); scene->LogicUpdateFrame(m_clockTime, false); // Actuators can affect the scenegraph m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_ACTUATOR); scene->UpdateParents(m_clockTime); scene->setSuspendedTime(0.0); } // suspended else if(scene->getSuspendedTime()==0.0) scene->setSuspendedTime(m_clockTime); DoSound(scene); m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true); } } m_previousClockTime = m_clockTime; // Start logging time spend outside main loop m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true); return doRender; }
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; }