12a1caee22150056e1922b1af0f95625b0d1367b
[blender.git] / source / gameengine / Ketsji / BL_Action.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Mitchell Stokes.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file BL_Action.cpp
24  *  \ingroup ketsji
25  */
26
27 #include <cstdlib>
28 #include <stdio.h>
29
30 #include "BL_Action.h"
31 #include "BL_ArmatureObject.h"
32 #include "BL_DeformableGameObject.h"
33 #include "BL_ShapeDeformer.h"
34 #include "KX_IpoConvert.h"
35 #include "KX_GameObject.h"
36
37 #include "SG_Controller.h"
38
39 // These three are for getting the action from the logic manager
40 #include "KX_Scene.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 // Needed for material IPOs
50 #include "BKE_material.h"
51 #include "DNA_material_types.h"
52 #include "DNA_scene_types.h"
53 }
54
55 #include "MEM_guardedalloc.h"
56 #include "BKE_library.h"
57 #include "BKE_global.h"
58
59 BL_Action::BL_Action(class KX_GameObject* gameobj)
60 :
61         m_action(NULL),
62         m_tmpaction(NULL),
63         m_blendpose(NULL),
64         m_blendinpose(NULL),
65         m_obj(gameobj),
66         m_startframe(0.f),
67         m_endframe(0.f),
68         m_endtime(0.f),
69         m_localtime(0.f),
70         m_blendin(0.f),
71         m_blendframe(0.f),
72         m_blendstart(0.f),
73         m_speed(0.f),
74         m_priority(0),
75         m_playmode(ACT_MODE_PLAY),
76         m_blendmode(ACT_BLEND_BLEND),
77         m_ipo_flags(0),
78         m_done(true),
79         m_calc_localtime(true)
80 {
81 }
82
83 BL_Action::~BL_Action()
84 {
85         if (m_blendpose)
86                 BKE_pose_free(m_blendpose);
87         if (m_blendinpose)
88                 BKE_pose_free(m_blendinpose);
89         ClearControllerList();
90
91         if (m_tmpaction) {
92                 BKE_libblock_free(G.main, m_tmpaction);
93                 m_tmpaction = NULL;
94         }
95 }
96
97 void BL_Action::ClearControllerList()
98 {
99         // Clear out the controller list
100         std::vector<SG_Controller*>::iterator it;
101         for (it = m_sg_contr_list.begin(); it != m_sg_contr_list.end(); it++)
102         {
103                 m_obj->GetSGNode()->RemoveSGController((*it));
104                 delete *it;
105         }
106
107         m_sg_contr_list.clear();
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                                         short blend_mode)
120 {
121
122         // Only start playing a new action if we're done, or if
123         // the new action has a higher priority
124         if (!IsDone() && priority > m_priority)
125                 return false;
126         m_priority = priority;
127         bAction* prev_action = m_action;
128
129         KX_Scene* kxscene = m_obj->GetScene();
130
131         // First try to load the action
132         m_action = (bAction*)kxscene->GetLogicManager()->GetActionByName(name);
133         if (!m_action)
134         {
135                 printf("Failed to load action: %s\n", name);
136                 m_done = true;
137                 return false;
138         }
139
140         // If we have the same settings, don't play again
141         // This is to resolve potential issues with pulses on sensors such as the ones
142         // reported in bug #29412. The fix is here so it works for both logic bricks and Python.
143         // However, this may eventually lead to issues where a user wants to override an already
144         // playing action with the same action and settings. If this becomes an issue,
145         // then this fix may have to be re-evaluated.
146         if (!IsDone() && m_action == prev_action && m_startframe == start && m_endframe == end
147                         && m_priority == priority && m_speed == playback_speed)
148                 return false;
149
150         // Keep a copy of the action for threading purposes
151         if (m_tmpaction) {
152                 BKE_libblock_free(G.main, m_tmpaction);
153                 m_tmpaction = NULL;
154         }
155         m_tmpaction = BKE_action_copy(m_action);
156
157         // First get rid of any old controllers
158         ClearControllerList();
159
160         // Create an SG_Controller
161         SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, kxscene->GetSceneConverter());
162         m_sg_contr_list.push_back(sg_contr);
163         m_obj->GetSGNode()->AddSGController(sg_contr);
164         sg_contr->SetObject(m_obj->GetSGNode());
165
166         // World
167         sg_contr = BL_CreateWorldIPO(m_action, kxscene->GetBlenderScene()->world, kxscene->GetSceneConverter());
168         if (sg_contr) {
169                 m_sg_contr_list.push_back(sg_contr);
170                 m_obj->GetSGNode()->AddSGController(sg_contr);
171                 sg_contr->SetObject(m_obj->GetSGNode());
172         }
173
174         // Try obcolor
175         sg_contr = BL_CreateObColorIPO(m_action, m_obj, kxscene->GetSceneConverter());
176         if (sg_contr) {
177                 m_sg_contr_list.push_back(sg_contr);
178                 m_obj->GetSGNode()->AddSGController(sg_contr);
179                 sg_contr->SetObject(m_obj->GetSGNode());
180         }
181
182         // Now try materials
183         if (m_obj->GetBlenderObject()->totcol==1) {
184                 Material *mat = give_current_material(m_obj->GetBlenderObject(), 1);
185                 if (mat) {
186                         sg_contr = BL_CreateMaterialIpo(m_action, mat, 0, m_obj, kxscene->GetSceneConverter());
187                         if (sg_contr) {
188                                 m_sg_contr_list.push_back(sg_contr);
189                                 m_obj->GetSGNode()->AddSGController(sg_contr);
190                                 sg_contr->SetObject(m_obj->GetSGNode());
191                         }
192                 }
193         } else {
194                 Material *mat;
195                 STR_HashedString matname;
196
197                 for (int matidx = 1; matidx <= m_obj->GetBlenderObject()->totcol; ++matidx) {
198                         mat = give_current_material(m_obj->GetBlenderObject(), matidx);
199                         if (mat) {
200                                 matname = mat->id.name;
201                                 sg_contr = BL_CreateMaterialIpo(m_action, mat, matname.hash(), m_obj, kxscene->GetSceneConverter());
202                                 if (sg_contr) {
203                                         m_sg_contr_list.push_back(sg_contr);
204                                         m_obj->GetSGNode()->AddSGController(sg_contr);
205                                         sg_contr->SetObject(m_obj->GetSGNode());
206                                 }
207                         }
208                 }
209         }
210
211         // Extra controllers
212         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT)
213         {
214                 sg_contr = BL_CreateLampIPO(m_action, m_obj, kxscene->GetSceneConverter());
215                 m_sg_contr_list.push_back(sg_contr);
216                 m_obj->GetSGNode()->AddSGController(sg_contr);
217                 sg_contr->SetObject(m_obj->GetSGNode());
218         }
219         else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA)
220         {
221                 sg_contr = BL_CreateCameraIPO(m_action, m_obj, kxscene->GetSceneConverter());
222                 m_sg_contr_list.push_back(sg_contr);
223                 m_obj->GetSGNode()->AddSGController(sg_contr);
224                 sg_contr->SetObject(m_obj->GetSGNode());
225         }
226         
227         m_ipo_flags = ipo_flags;
228         InitIPO();
229
230         // Setup blendin shapes/poses
231         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
232         {
233                 BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
234                 obj->GetPose(&m_blendinpose);
235         }
236         else
237         {
238                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
239                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
240                 
241                 if (shape_deformer && shape_deformer->GetKey())
242                 {
243                         obj->GetShape(m_blendinshape);
244
245                         // Now that we have the previous blend shape saved, we can clear out the key to avoid any
246                         // further interference.
247                         KeyBlock *kb;
248                         for (kb=(KeyBlock *)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock *)kb->next)
249                                 kb->curval = 0.f;
250                 }
251         }
252
253         // Now that we have an action, we have something we can play
254         m_starttime = -1.f; // We get the start time on our first update
255         m_startframe = m_localtime = start;
256         m_endframe = end;
257         m_blendin = blendin;
258         m_playmode = play_mode;
259         m_blendmode = blend_mode;
260         m_endtime = 0.f;
261         m_blendframe = 0.f;
262         m_blendstart = 0.f;
263         m_speed = playback_speed;
264         m_layer_weight = layer_weight;
265         
266         m_done = false;
267
268         return true;
269 }
270
271 void BL_Action::Stop()
272 {
273         m_done = true;
274 }
275
276 bool BL_Action::IsDone()
277 {
278         return m_done;
279 }
280
281 void BL_Action::InitIPO()
282 {
283         // Initialize the IPOs
284         std::vector<SG_Controller*>::iterator it;
285         for (it = m_sg_contr_list.begin(); it != m_sg_contr_list.end(); it++)
286         {
287                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
288                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, m_ipo_flags & ACT_IPOFLAG_FORCE);
289                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, m_ipo_flags & ACT_IPOFLAG_ADD);
290                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, m_ipo_flags & ACT_IPOFLAG_LOCAL);
291         }
292 }
293
294 bAction *BL_Action::GetAction()
295 {
296         return (IsDone()) ? NULL : m_action;
297 }
298
299 float BL_Action::GetFrame()
300 {
301         return m_localtime;
302 }
303
304 const char *BL_Action::GetName()
305 {
306         if (m_action != NULL) {
307                 return m_action->id.name + 2;
308         }
309         else {
310                 return "";
311         }
312
313                     
314 }
315
316 void BL_Action::SetFrame(float frame)
317 {
318         // Clamp the frame to the start and end frame
319         if (frame < min(m_startframe, m_endframe))
320                 frame = min(m_startframe, m_endframe);
321         else if (frame > max(m_startframe, m_endframe))
322                 frame = max(m_startframe, m_endframe);
323         
324         m_localtime = frame;
325         m_calc_localtime = false;
326 }
327
328 void BL_Action::SetPlayMode(short play_mode)
329 {
330         m_playmode = play_mode;
331 }
332
333 void BL_Action::SetTimes(float start, float end)
334 {
335         m_startframe = start;
336         m_endframe = end;
337 }
338
339 void BL_Action::SetLocalTime(float curtime)
340 {
341         float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate()*m_speed;
342
343         if (m_endframe < m_startframe)
344                 dt = -dt;
345
346         m_localtime = m_startframe + dt;
347 }
348
349 void BL_Action::ResetStartTime(float curtime)
350 {
351         float dt = (m_localtime > m_startframe) ? m_localtime - m_startframe : m_startframe - m_localtime;
352
353         m_starttime = curtime - dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed);
354         SetLocalTime(curtime);
355 }
356
357 void BL_Action::IncrementBlending(float curtime)
358 {
359         // Setup m_blendstart if we need to
360         if (m_blendstart == 0.f)
361                 m_blendstart = curtime;
362         
363         // Bump the blend frame
364         m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
365
366         // Clamp
367         if (m_blendframe>m_blendin)
368                 m_blendframe = m_blendin;
369 }
370
371
372 void BL_Action::BlendShape(Key* key, float srcweight, std::vector<float>& blendshape)
373 {
374         vector<float>::const_iterator it;
375         float dstweight;
376         KeyBlock *kb;
377         
378         dstweight = 1.0F - srcweight;
379         //printf("Dst: %f\tSrc: %f\n", srcweight, dstweight);
380         for (it=blendshape.begin(), kb = (KeyBlock *)key->block.first; 
381              kb && it != blendshape.end();
382              kb = (KeyBlock *)kb->next, it++)
383         {
384                 //printf("OirgKeys: %f\t%f\n", kb->curval, (*it));
385                 kb->curval = kb->curval * dstweight + (*it) * srcweight;
386                 //printf("NewKey: %f\n", kb->curval);
387         }
388         //printf("\n");
389 }
390
391 void BL_Action::Update(float curtime)
392 {
393         // Don't bother if we're done with the animation
394         if (m_done)
395                 return;
396
397         curtime -= KX_KetsjiEngine::GetSuspendedDelta();
398
399         // Grab the start time here so we don't end up with a negative m_localtime when
400         // suspending and resuming scenes.
401         if (m_starttime < 0)
402                 m_starttime = curtime;
403
404         if (m_calc_localtime)
405                 SetLocalTime(curtime);
406         else
407         {
408                 ResetStartTime(curtime);
409                 m_calc_localtime = true;
410         }
411
412         // Handle wrap around
413         if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe)) {
414                 switch (m_playmode) {
415                         case ACT_MODE_PLAY:
416                                 // Clamp
417                                 m_localtime = m_endframe;
418                                 m_done = true;
419                                 break;
420                         case ACT_MODE_LOOP:
421                                 // Put the time back to the beginning
422                                 m_localtime = m_startframe;
423                                 m_starttime = curtime;
424                                 break;
425                         case ACT_MODE_PING_PONG:
426                                 // Swap the start and end frames
427                                 float temp = m_startframe;
428                                 m_startframe = m_endframe;
429                                 m_endframe = temp;
430
431                                 m_starttime = curtime;
432
433                                 break;
434                 }
435         }
436
437         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
438         {
439                 BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
440
441                 if (m_layer_weight >= 0)
442                         obj->GetPose(&m_blendpose);
443
444                 // Extract the pose from the action
445                 obj->SetPoseByAction(m_tmpaction, m_localtime);
446
447                 // Handle blending between armature actions
448                 if (m_blendin && m_blendframe<m_blendin)
449                 {
450                         IncrementBlending(curtime);
451
452                         // Calculate weight
453                         float weight = 1.f - (m_blendframe/m_blendin);
454
455                         // Blend the poses
456                         obj->BlendInPose(m_blendinpose, weight, ACT_BLEND_BLEND);
457                 }
458
459
460                 // Handle layer blending
461                 if (m_layer_weight >= 0)
462                         obj->BlendInPose(m_blendpose, m_layer_weight, m_blendmode);
463
464                 obj->UpdateTimestep(curtime);
465         }
466         else
467         {
468                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
469                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
470
471                 // Handle shape actions if we have any
472                 if (shape_deformer && shape_deformer->GetKey())
473                 {
474                         Key *key = shape_deformer->GetKey();
475
476                         PointerRNA ptrrna;
477                         RNA_id_pointer_create(&key->id, &ptrrna);
478
479                         animsys_evaluate_action(&ptrrna, m_tmpaction, NULL, m_localtime);
480
481                         // Handle blending between shape actions
482                         if (m_blendin && m_blendframe < m_blendin)
483                         {
484                                 IncrementBlending(curtime);
485
486                                 float weight = 1.f - (m_blendframe/m_blendin);
487
488                                 // We go through and clear out the keyblocks so there isn't any interference
489                                 // from other shape actions
490                                 KeyBlock *kb;
491                                 for (kb=(KeyBlock *)key->block.first; kb; kb=(KeyBlock *)kb->next)
492                                         kb->curval = 0.f;
493
494                                 // Now blend the shape
495                                 BlendShape(key, weight, m_blendinshape);
496                         }
497
498                         // Handle layer blending
499                         if (m_layer_weight >= 0)
500                         {
501                                 obj->GetShape(m_blendshape);
502                                 BlendShape(key, m_layer_weight, m_blendshape);
503                         }
504
505                         obj->SetActiveAction(NULL, 0, curtime);
506                 }
507         }
508
509         // This isn't thread-safe, so we move it into it's own function for now
510         //m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD);
511
512         if (m_done)
513                 ClearControllerList();
514 }
515
516 void BL_Action::UpdateIPOs()
517 {
518         if (!m_done)
519                 m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD);
520 }