svn merge -r39145:39286 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / gameengine / Ketsji / BL_Action.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * Contributor(s): Mitchell Stokes.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file BL_Action.cpp
26  *  \ingroup ketsji
27  */
28
29 #include <cstdlib>
30
31 #include "BL_Action.h"
32 #include "BL_ArmatureObject.h"
33 #include "BL_DeformableGameObject.h"
34 #include "BL_ShapeDeformer.h"
35 #include "KX_IpoConvert.h"
36 #include "KX_GameObject.h"
37
38 // These three are for getting the action from the logic manager
39 #include "KX_Scene.h"
40 #include "KX_PythonInit.h"
41 #include "SCA_LogicManager.h"
42
43 extern "C" {
44 #include "BKE_animsys.h"
45 #include "BKE_action.h"
46 #include "RNA_access.h"
47 #include "RNA_define.h"
48 }
49
50 BL_Action::BL_Action(class KX_GameObject* gameobj)
51 :
52         m_action(NULL),
53         m_pose(NULL),
54         m_blendpose(NULL),
55         m_blendinpose(NULL),
56         m_ptrrna(NULL),
57         m_sg_contr(NULL),
58         m_obj(gameobj),
59         m_startframe(0.f),
60         m_endframe(0.f),
61         m_endtime(0.f),
62         m_localtime(0.f),
63         m_blendin(0.f),
64         m_blendframe(0.f),
65         m_blendstart(0.f),
66         m_speed(0.f),
67         m_priority(0),
68         m_playmode(0),
69         m_ipo_flags(0),
70         m_done(true),
71         m_calc_localtime(true)
72 {
73         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
74         {
75                 BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
76
77                 m_ptrrna = new PointerRNA();
78                 RNA_id_pointer_create(&obj->GetArmatureObject()->id, m_ptrrna);
79         }
80         else
81         {
82                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
83                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
84
85                 if (shape_deformer)
86                 {
87                         m_ptrrna = new PointerRNA();
88                         RNA_id_pointer_create(&shape_deformer->GetKey()->id, m_ptrrna);
89                 }
90         }
91 }
92
93 BL_Action::~BL_Action()
94 {
95         if (m_pose)
96                 game_free_pose(m_pose);
97         if (m_blendpose)
98                 game_free_pose(m_blendpose);
99         if (m_blendinpose)
100                 game_free_pose(m_blendinpose);
101         if (m_sg_contr)
102         {
103                 m_obj->GetSGNode()->RemoveSGController(m_sg_contr);
104                 delete m_sg_contr;
105         }
106         if (m_ptrrna)
107                 delete m_ptrrna;
108 }
109
110 bool BL_Action::Play(const char* name,
111                                         float start,
112                                         float end,
113                                         short priority,
114                                         float blendin,
115                                         short play_mode,
116                                         float layer_weight,
117                                         short ipo_flags,
118                                         float playback_speed)
119 {
120
121         // Only start playing a new action if we're done, or if
122         // the new action has a higher priority
123         if (priority != 0 && !IsDone() && priority >= m_priority)
124                 return false;
125         m_priority = priority;
126         bAction* prev_action = m_action;
127
128         // First try to load the action
129         m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name);
130         if (!m_action)
131         {
132                 printf("Failed to load action: %s\n", name);
133                 m_done = true;
134                 return false;
135         }
136
137         if (prev_action != m_action)
138         {
139                 // Create an SG_Controller
140                 m_sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
141                 m_obj->GetSGNode()->AddSGController(m_sg_contr);
142                 m_sg_contr->SetObject(m_obj->GetSGNode());
143         }
144         
145         m_ipo_flags = ipo_flags;
146         InitIPO();
147
148         // Setup blendin shapes/poses
149         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
150         {
151                 BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
152                 obj->GetMRDPose(&m_blendinpose);
153         }
154         else
155         {
156                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
157                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
158                 
159                 if (shape_deformer && shape_deformer->GetKey())
160                 {
161                         obj->GetShape(m_blendinshape);
162
163                         // Now that we have the previous blend shape saved, we can clear out the key to avoid any
164                         // further interference.
165                         KeyBlock *kb;
166                         for (kb=(KeyBlock*)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock*)kb->next)
167                                 kb->curval = 0.f;
168                 }
169         }
170
171         // Now that we have an action, we have something we can play
172         m_starttime = KX_GetActiveEngine()->GetFrameTime();
173         m_startframe = m_localtime = start;
174         m_endframe = end;
175         m_blendin = blendin;
176         m_playmode = play_mode;
177         m_endtime = 0.f;
178         m_blendframe = 0.f;
179         m_blendstart = 0.f;
180         m_speed = playback_speed;
181         m_layer_weight = layer_weight;
182         
183         m_done = false;
184
185         return true;
186 }
187
188 void BL_Action::Stop()
189 {
190         m_done = true;
191 }
192
193 bool BL_Action::IsDone()
194 {
195         return m_done;
196 }
197
198 void BL_Action::InitIPO()
199 {
200                 // Initialize the IPO
201                 m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
202                 m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, m_ipo_flags & ACT_IPOFLAG_FORCE);
203                 m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, m_ipo_flags & ACT_IPOFLAG_ADD);
204                 m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, m_ipo_flags & ACT_IPOFLAG_LOCAL);
205 }
206
207 bAction *BL_Action::GetAction()
208 {
209         return (IsDone()) ? NULL : m_action;
210 }
211
212 float BL_Action::GetFrame()
213 {
214         return m_localtime;
215 }
216
217 void BL_Action::SetFrame(float frame)
218 {
219         // Clamp the frame to the start and end frame
220         if (frame < min(m_startframe, m_endframe))
221                 frame = min(m_startframe, m_endframe);
222         else if (frame > max(m_startframe, m_endframe))
223                 frame = max(m_startframe, m_endframe);
224         
225         m_localtime = frame;
226         m_calc_localtime = false;
227 }
228
229 void BL_Action::SetPlayMode(short play_mode)
230 {
231         m_playmode = play_mode;
232 }
233
234 void BL_Action::SetTimes(float start, float end)
235 {
236         m_startframe = start;
237         m_endframe = end;
238 }
239
240 void BL_Action::SetLocalTime(float curtime)
241 {
242         float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate()*m_speed;
243
244         if (m_endframe < m_startframe)
245                 dt = -dt;
246
247         m_localtime = m_startframe + dt;
248 }
249
250 void BL_Action::ResetStartTime(float curtime)
251 {
252         float dt = m_localtime - m_startframe;
253
254         m_starttime = curtime - dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed);
255         SetLocalTime(curtime);
256 }
257
258 void BL_Action::IncrementBlending(float curtime)
259 {
260         // Setup m_blendstart if we need to
261         if (m_blendstart == 0.f)
262                 m_blendstart = curtime;
263         
264         // Bump the blend frame
265         m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
266
267         // Clamp
268         if (m_blendframe>m_blendin)
269                 m_blendframe = m_blendin;
270 }
271
272
273 void BL_Action::BlendShape(Key* key, float srcweight, std::vector<float>& blendshape)
274 {
275         vector<float>::const_iterator it;
276         float dstweight;
277         KeyBlock *kb;
278         
279         dstweight = 1.0F - srcweight;
280         //printf("Dst: %f\tSrc: %f\n", srcweight, dstweight);
281         for (it=blendshape.begin(), kb = (KeyBlock*)key->block.first; 
282                  kb && it != blendshape.end(); 
283                  kb = (KeyBlock*)kb->next, it++) {
284                 //printf("OirgKeys: %f\t%f\n", kb->curval, (*it));
285                 kb->curval = kb->curval * dstweight + (*it) * srcweight;
286                 //printf("NewKey: %f\n", kb->curval);
287         }
288         //printf("\n");
289 }
290
291 void BL_Action::Update(float curtime)
292 {
293         // Don't bother if we're done with the animation
294         if (m_done)
295                 return;
296
297         curtime -= KX_KetsjiEngine::GetSuspendedDelta();
298
299         if (m_calc_localtime)
300                 SetLocalTime(curtime);
301         else
302         {
303                 ResetStartTime(curtime);
304                 m_calc_localtime = true;
305         }
306
307         // Handle wrap around
308         if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe))
309         {
310                 switch(m_playmode)
311                 {
312                 case ACT_MODE_PLAY:
313                         // Clamp
314                         m_localtime = m_endframe;
315                         m_done = true;
316                         break;
317                 case ACT_MODE_LOOP:
318                         // Put the time back to the beginning
319                         m_localtime = m_startframe;
320                         m_starttime = curtime;
321                         break;
322                 case ACT_MODE_PING_PONG:
323                         // Swap the start and end frames
324                         float temp = m_startframe;
325                         m_startframe = m_endframe;
326                         m_endframe = temp;
327
328                         m_starttime = curtime;
329
330                         break;
331                 }
332
333                 if (!m_done && m_sg_contr)
334                         InitIPO();
335         }
336
337         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
338         {
339                 BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
340                 obj->GetPose(&m_pose);
341
342                 // Extract the pose from the action
343                 {
344                         Object *arm = obj->GetArmatureObject();
345                         bPose *temp = arm->pose;
346
347                         arm->pose = m_pose;
348                         animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime);
349
350                         arm->pose = temp;
351                 }
352
353                 // Handle blending between armature actions
354                 if (m_blendin && m_blendframe<m_blendin)
355                 {
356                         IncrementBlending(curtime);
357
358                         // Calculate weight
359                         float weight = 1.f - (m_blendframe/m_blendin);
360
361                         // Blend the poses
362                         game_blend_poses(m_pose, m_blendinpose, weight);
363                 }
364
365
366                 // Handle layer blending
367                 if (m_layer_weight >= 0)
368                 {
369                         obj->GetMRDPose(&m_blendpose);
370                         game_blend_poses(m_pose, m_blendpose, m_layer_weight);
371                 }
372
373                 obj->SetPose(m_pose);
374
375                 obj->SetActiveAction(NULL, 0, curtime);
376         }
377         else
378         {
379                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
380                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
381
382                 // Handle shape actions if we have any
383                 if (shape_deformer && shape_deformer->GetKey())
384                 {
385                         Key *key = shape_deformer->GetKey();
386
387
388                         animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime);
389
390                         // Handle blending between shape actions
391                         if (m_blendin && m_blendframe < m_blendin)
392                         {
393                                 IncrementBlending(curtime);
394
395                                 float weight = 1.f - (m_blendframe/m_blendin);
396
397                                 // We go through and clear out the keyblocks so there isn't any interference
398                                 // from other shape actions
399                                 KeyBlock *kb;
400                                 for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next)
401                                         kb->curval = 0.f;
402
403                                 // Now blend the shape
404                                 BlendShape(key, weight, m_blendinshape);
405                         }
406
407                         // Handle layer blending
408                         if (m_layer_weight >= 0)
409                         {
410                                 obj->GetShape(m_blendshape);
411                                 BlendShape(key, m_layer_weight, m_blendshape);
412                         }
413
414                         obj->SetActiveAction(NULL, 0, curtime);
415                 }
416
417
418                 InitIPO();
419                 m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD);
420         }
421 }