Blender V2.61 - r43446

BL_Action.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Mitchell Stokes.
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00027 #include <cstdlib>
00028 
00029 #include "BL_Action.h"
00030 #include "BL_ArmatureObject.h"
00031 #include "BL_DeformableGameObject.h"
00032 #include "BL_ShapeDeformer.h"
00033 #include "KX_IpoConvert.h"
00034 #include "KX_GameObject.h"
00035 
00036 // These three are for getting the action from the logic manager
00037 #include "KX_Scene.h"
00038 #include "KX_PythonInit.h"
00039 #include "SCA_LogicManager.h"
00040 
00041 extern "C" {
00042 #include "BKE_animsys.h"
00043 #include "BKE_action.h"
00044 #include "RNA_access.h"
00045 #include "RNA_define.h"
00046 }
00047 
00048 BL_Action::BL_Action(class KX_GameObject* gameobj)
00049 :
00050     m_action(NULL),
00051     m_pose(NULL),
00052     m_blendpose(NULL),
00053     m_blendinpose(NULL),
00054     m_ptrrna(NULL),
00055     m_obj(gameobj),
00056     m_startframe(0.f),
00057     m_endframe(0.f),
00058     m_endtime(0.f),
00059     m_localtime(0.f),
00060     m_blendin(0.f),
00061     m_blendframe(0.f),
00062     m_blendstart(0.f),
00063     m_speed(0.f),
00064     m_priority(0),
00065     m_playmode(0),
00066     m_ipo_flags(0),
00067     m_done(true),
00068     m_calc_localtime(true)
00069 {
00070     if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
00071     {
00072         BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
00073 
00074         m_ptrrna = new PointerRNA();
00075         RNA_id_pointer_create(&obj->GetArmatureObject()->id, m_ptrrna);
00076     }
00077     else
00078     {
00079         BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
00080         BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
00081 
00082         if (shape_deformer)
00083         {
00084             m_ptrrna = new PointerRNA();
00085             RNA_id_pointer_create(&shape_deformer->GetKey()->id, m_ptrrna);
00086         }
00087     }
00088 }
00089 
00090 BL_Action::~BL_Action()
00091 {
00092     if (m_pose)
00093         game_free_pose(m_pose);
00094     if (m_blendpose)
00095         game_free_pose(m_blendpose);
00096     if (m_blendinpose)
00097         game_free_pose(m_blendinpose);
00098     if (m_ptrrna)
00099         delete m_ptrrna;
00100     ClearControllerList();
00101 }
00102 
00103 void BL_Action::ClearControllerList()
00104 {
00105     // Clear out the controller list
00106     std::vector<SG_Controller*>::iterator it;
00107     for (it = m_sg_contr_list.begin(); it != m_sg_contr_list.end(); it++)
00108     {
00109         m_obj->GetSGNode()->RemoveSGController((*it));
00110         delete *it;
00111     }
00112 
00113     m_sg_contr_list.clear();
00114 }
00115 
00116 bool BL_Action::Play(const char* name,
00117                     float start,
00118                     float end,
00119                     short priority,
00120                     float blendin,
00121                     short play_mode,
00122                     float layer_weight,
00123                     short ipo_flags,
00124                     float playback_speed)
00125 {
00126 
00127     // Only start playing a new action if we're done, or if
00128     // the new action has a higher priority
00129     if (priority != 0 && !IsDone() && priority >= m_priority)
00130         return false;
00131     m_priority = priority;
00132     bAction* prev_action = m_action;
00133 
00134     // First try to load the action
00135     m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name);
00136     if (!m_action)
00137     {
00138         printf("Failed to load action: %s\n", name);
00139         m_done = true;
00140         return false;
00141     }
00142 
00143     if (prev_action != m_action)
00144     {
00145         // First get rid of any old controllers
00146         ClearControllerList();
00147 
00148         // Create an SG_Controller
00149         SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
00150         m_sg_contr_list.push_back(sg_contr);
00151         m_obj->GetSGNode()->AddSGController(sg_contr);
00152         sg_contr->SetObject(m_obj->GetSGNode());
00153 
00154         // Extra controllers
00155         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT)
00156         {
00157             sg_contr = BL_CreateLampIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
00158             m_sg_contr_list.push_back(sg_contr);
00159             m_obj->GetSGNode()->AddSGController(sg_contr);
00160             sg_contr->SetObject(m_obj->GetSGNode());
00161         }
00162         else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA)
00163         {
00164             sg_contr = BL_CreateCameraIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
00165             m_sg_contr_list.push_back(sg_contr);
00166             m_obj->GetSGNode()->AddSGController(sg_contr);
00167             sg_contr->SetObject(m_obj->GetSGNode());
00168         }
00169     }
00170     
00171     m_ipo_flags = ipo_flags;
00172     InitIPO();
00173 
00174     // Setup blendin shapes/poses
00175     if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
00176     {
00177         BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
00178         obj->GetMRDPose(&m_blendinpose);
00179     }
00180     else
00181     {
00182         BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
00183         BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
00184         
00185         if (shape_deformer && shape_deformer->GetKey())
00186         {
00187             obj->GetShape(m_blendinshape);
00188 
00189             // Now that we have the previous blend shape saved, we can clear out the key to avoid any
00190             // further interference.
00191             KeyBlock *kb;
00192             for (kb=(KeyBlock*)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock*)kb->next)
00193                 kb->curval = 0.f;
00194         }
00195     }
00196 
00197     // Now that we have an action, we have something we can play
00198     m_starttime = KX_GetActiveEngine()->GetFrameTime();
00199     m_startframe = m_localtime = start;
00200     m_endframe = end;
00201     m_blendin = blendin;
00202     m_playmode = play_mode;
00203     m_endtime = 0.f;
00204     m_blendframe = 0.f;
00205     m_blendstart = 0.f;
00206     m_speed = playback_speed;
00207     m_layer_weight = layer_weight;
00208     
00209     m_done = false;
00210 
00211     return true;
00212 }
00213 
00214 void BL_Action::Stop()
00215 {
00216     m_done = true;
00217 }
00218 
00219 bool BL_Action::IsDone()
00220 {
00221     return m_done;
00222 }
00223 
00224 void BL_Action::InitIPO()
00225 {
00226     // Initialize the IPOs
00227     std::vector<SG_Controller*>::iterator it;
00228     for (it = m_sg_contr_list.begin(); it != m_sg_contr_list.end(); it++)
00229     {
00230         (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
00231         (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, m_ipo_flags & ACT_IPOFLAG_FORCE);
00232         (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, m_ipo_flags & ACT_IPOFLAG_ADD);
00233         (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, m_ipo_flags & ACT_IPOFLAG_LOCAL);
00234     }
00235 }
00236 
00237 bAction *BL_Action::GetAction()
00238 {
00239     return (IsDone()) ? NULL : m_action;
00240 }
00241 
00242 float BL_Action::GetFrame()
00243 {
00244     return m_localtime;
00245 }
00246 
00247 void BL_Action::SetFrame(float frame)
00248 {
00249     // Clamp the frame to the start and end frame
00250     if (frame < min(m_startframe, m_endframe))
00251         frame = min(m_startframe, m_endframe);
00252     else if (frame > max(m_startframe, m_endframe))
00253         frame = max(m_startframe, m_endframe);
00254     
00255     m_localtime = frame;
00256     m_calc_localtime = false;
00257 }
00258 
00259 void BL_Action::SetPlayMode(short play_mode)
00260 {
00261     m_playmode = play_mode;
00262 }
00263 
00264 void BL_Action::SetTimes(float start, float end)
00265 {
00266     m_startframe = start;
00267     m_endframe = end;
00268 }
00269 
00270 void BL_Action::SetLocalTime(float curtime)
00271 {
00272     float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate()*m_speed;
00273 
00274     if (m_endframe < m_startframe)
00275         dt = -dt;
00276 
00277     m_localtime = m_startframe + dt;
00278 }
00279 
00280 void BL_Action::ResetStartTime(float curtime)
00281 {
00282     float dt = (m_localtime > m_startframe) ? m_localtime - m_startframe : m_startframe - m_localtime;
00283 
00284     m_starttime = curtime - dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed);
00285     SetLocalTime(curtime);
00286 }
00287 
00288 void BL_Action::IncrementBlending(float curtime)
00289 {
00290     // Setup m_blendstart if we need to
00291     if (m_blendstart == 0.f)
00292         m_blendstart = curtime;
00293     
00294     // Bump the blend frame
00295     m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
00296 
00297     // Clamp
00298     if (m_blendframe>m_blendin)
00299         m_blendframe = m_blendin;
00300 }
00301 
00302 
00303 void BL_Action::BlendShape(Key* key, float srcweight, std::vector<float>& blendshape)
00304 {
00305     vector<float>::const_iterator it;
00306     float dstweight;
00307     KeyBlock *kb;
00308     
00309     dstweight = 1.0F - srcweight;
00310     //printf("Dst: %f\tSrc: %f\n", srcweight, dstweight);
00311     for (it=blendshape.begin(), kb = (KeyBlock*)key->block.first; 
00312          kb && it != blendshape.end();
00313          kb = (KeyBlock*)kb->next, it++)
00314     {
00315         //printf("OirgKeys: %f\t%f\n", kb->curval, (*it));
00316         kb->curval = kb->curval * dstweight + (*it) * srcweight;
00317         //printf("NewKey: %f\n", kb->curval);
00318     }
00319     //printf("\n");
00320 }
00321 
00322 void BL_Action::Update(float curtime)
00323 {
00324     // Don't bother if we're done with the animation
00325     if (m_done)
00326         return;
00327 
00328     curtime -= KX_KetsjiEngine::GetSuspendedDelta();
00329 
00330     if (m_calc_localtime)
00331         SetLocalTime(curtime);
00332     else
00333     {
00334         ResetStartTime(curtime);
00335         m_calc_localtime = true;
00336     }
00337 
00338     // Handle wrap around
00339     if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe))
00340     {
00341         switch(m_playmode)
00342         {
00343         case ACT_MODE_PLAY:
00344             // Clamp
00345             m_localtime = m_endframe;
00346             m_done = true;
00347             break;
00348         case ACT_MODE_LOOP:
00349             // Put the time back to the beginning
00350             m_localtime = m_startframe;
00351             m_starttime = curtime;
00352             break;
00353         case ACT_MODE_PING_PONG:
00354             // Swap the start and end frames
00355             float temp = m_startframe;
00356             m_startframe = m_endframe;
00357             m_endframe = temp;
00358 
00359             m_starttime = curtime;
00360 
00361             break;
00362         }
00363     }
00364 
00365     if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
00366     {
00367         BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
00368         obj->GetPose(&m_pose);
00369 
00370         // Extract the pose from the action
00371         {
00372             Object *arm = obj->GetArmatureObject();
00373             bPose *temp = arm->pose;
00374 
00375             arm->pose = m_pose;
00376             animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime);
00377 
00378             arm->pose = temp;
00379         }
00380 
00381         // Handle blending between armature actions
00382         if (m_blendin && m_blendframe<m_blendin)
00383         {
00384             IncrementBlending(curtime);
00385 
00386             // Calculate weight
00387             float weight = 1.f - (m_blendframe/m_blendin);
00388 
00389             // Blend the poses
00390             game_blend_poses(m_pose, m_blendinpose, weight);
00391         }
00392 
00393 
00394         // Handle layer blending
00395         if (m_layer_weight >= 0)
00396         {
00397             obj->GetMRDPose(&m_blendpose);
00398             game_blend_poses(m_pose, m_blendpose, m_layer_weight);
00399         }
00400 
00401         obj->SetPose(m_pose);
00402 
00403         obj->SetActiveAction(NULL, 0, curtime);
00404     }
00405     else
00406     {
00407         BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
00408         BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
00409 
00410         // Handle shape actions if we have any
00411         if (shape_deformer && shape_deformer->GetKey())
00412         {
00413             Key *key = shape_deformer->GetKey();
00414 
00415 
00416             animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime);
00417 
00418             // Handle blending between shape actions
00419             if (m_blendin && m_blendframe < m_blendin)
00420             {
00421                 IncrementBlending(curtime);
00422 
00423                 float weight = 1.f - (m_blendframe/m_blendin);
00424 
00425                 // We go through and clear out the keyblocks so there isn't any interference
00426                 // from other shape actions
00427                 KeyBlock *kb;
00428                 for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next)
00429                     kb->curval = 0.f;
00430 
00431                 // Now blend the shape
00432                 BlendShape(key, weight, m_blendinshape);
00433             }
00434 
00435             // Handle layer blending
00436             if (m_layer_weight >= 0)
00437             {
00438                 obj->GetShape(m_blendshape);
00439                 BlendShape(key, m_layer_weight, m_blendshape);
00440             }
00441 
00442             obj->SetActiveAction(NULL, 0, curtime);
00443         }
00444 
00445         m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD);
00446     }
00447 }