1d5a3dd461a62e69e1e15c776db300da2e6feb27
[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
29 #include "BL_Action.h"
30 #include "BL_ArmatureObject.h"
31 #include "BL_DeformableGameObject.h"
32 #include "BL_ShapeDeformer.h"
33 #include "KX_IpoConvert.h"
34 #include "KX_GameObject.h"
35
36 // These three are for getting the action from the logic manager
37 #include "KX_Scene.h"
38 #include "KX_PythonInit.h"
39 #include "SCA_LogicManager.h"
40
41 extern "C" {
42 #include "BKE_animsys.h"
43 #include "BKE_action.h"
44 #include "RNA_access.h"
45 #include "RNA_define.h"
46 }
47
48 BL_Action::BL_Action(class KX_GameObject* gameobj)
49 :
50         m_action(NULL),
51         m_pose(NULL),
52         m_blendpose(NULL),
53         m_blendinpose(NULL),
54         m_ptrrna(NULL),
55         m_obj(gameobj),
56         m_startframe(0.f),
57         m_endframe(0.f),
58         m_endtime(0.f),
59         m_localtime(0.f),
60         m_blendin(0.f),
61         m_blendframe(0.f),
62         m_blendstart(0.f),
63         m_speed(0.f),
64         m_priority(0),
65         m_playmode(0),
66         m_ipo_flags(0),
67         m_done(true),
68         m_calc_localtime(true)
69 {
70         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
71         {
72                 BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
73
74                 m_ptrrna = new PointerRNA();
75                 RNA_id_pointer_create(&obj->GetArmatureObject()->id, m_ptrrna);
76         }
77         else
78         {
79                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
80                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
81
82                 if (shape_deformer)
83                 {
84                         m_ptrrna = new PointerRNA();
85                         RNA_id_pointer_create(&shape_deformer->GetKey()->id, m_ptrrna);
86                 }
87         }
88 }
89
90 BL_Action::~BL_Action()
91 {
92         if (m_pose)
93                 game_free_pose(m_pose);
94         if (m_blendpose)
95                 game_free_pose(m_blendpose);
96         if (m_blendinpose)
97                 game_free_pose(m_blendinpose);
98         if (m_ptrrna)
99                 delete m_ptrrna;
100         ClearControllerList();
101 }
102
103 void BL_Action::ClearControllerList()
104 {
105         // Clear out the controller list
106         std::vector<SG_Controller*>::iterator it;
107         for (it = m_sg_contr_list.begin(); it != m_sg_contr_list.end(); it++)
108         {
109                 m_obj->GetSGNode()->RemoveSGController((*it));
110                 delete *it;
111         }
112
113         m_sg_contr_list.clear();
114 }
115
116 bool BL_Action::Play(const char* name,
117                                         float start,
118                                         float end,
119                                         short priority,
120                                         float blendin,
121                                         short play_mode,
122                                         float layer_weight,
123                                         short ipo_flags,
124                                         float playback_speed)
125 {
126
127         // Only start playing a new action if we're done, or if
128         // the new action has a higher priority
129         if (priority != 0 && !IsDone() && priority >= m_priority)
130                 return false;
131         m_priority = priority;
132         bAction* prev_action = m_action;
133
134         // First try to load the action
135         m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name);
136         if (!m_action)
137         {
138                 printf("Failed to load action: %s\n", name);
139                 m_done = true;
140                 return false;
141         }
142
143         if (prev_action != m_action)
144         {
145                 // First get rid of any old controllers
146                 ClearControllerList();
147
148                 // Create an SG_Controller
149                 SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
150                 m_sg_contr_list.push_back(sg_contr);
151                 m_obj->GetSGNode()->AddSGController(sg_contr);
152                 sg_contr->SetObject(m_obj->GetSGNode());
153
154                 // Extra controllers
155                 if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT)
156                 {
157                         sg_contr = BL_CreateLampIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
158                         m_sg_contr_list.push_back(sg_contr);
159                         m_obj->GetSGNode()->AddSGController(sg_contr);
160                         sg_contr->SetObject(m_obj->GetSGNode());
161                 }
162                 else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA)
163                 {
164                         sg_contr = BL_CreateCameraIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
165                         m_sg_contr_list.push_back(sg_contr);
166                         m_obj->GetSGNode()->AddSGController(sg_contr);
167                         sg_contr->SetObject(m_obj->GetSGNode());
168                 }
169         }
170         
171         m_ipo_flags = ipo_flags;
172         InitIPO();
173
174         // Setup blendin shapes/poses
175         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
176         {
177                 BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
178                 obj->GetMRDPose(&m_blendinpose);
179         }
180         else
181         {
182                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
183                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
184                 
185                 if (shape_deformer && shape_deformer->GetKey())
186                 {
187                         obj->GetShape(m_blendinshape);
188
189                         // Now that we have the previous blend shape saved, we can clear out the key to avoid any
190                         // further interference.
191                         KeyBlock *kb;
192                         for (kb=(KeyBlock*)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock*)kb->next)
193                                 kb->curval = 0.f;
194                 }
195         }
196
197         // Now that we have an action, we have something we can play
198         m_starttime = KX_GetActiveEngine()->GetFrameTime();
199         m_startframe = m_localtime = start;
200         m_endframe = end;
201         m_blendin = blendin;
202         m_playmode = play_mode;
203         m_endtime = 0.f;
204         m_blendframe = 0.f;
205         m_blendstart = 0.f;
206         m_speed = playback_speed;
207         m_layer_weight = layer_weight;
208         
209         m_done = false;
210
211         return true;
212 }
213
214 void BL_Action::Stop()
215 {
216         m_done = true;
217 }
218
219 bool BL_Action::IsDone()
220 {
221         return m_done;
222 }
223
224 void BL_Action::InitIPO()
225 {
226         // Initialize the IPOs
227         std::vector<SG_Controller*>::iterator it;
228         for (it = m_sg_contr_list.begin(); it != m_sg_contr_list.end(); it++)
229         {
230                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
231                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, m_ipo_flags & ACT_IPOFLAG_FORCE);
232                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, m_ipo_flags & ACT_IPOFLAG_ADD);
233                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, m_ipo_flags & ACT_IPOFLAG_LOCAL);
234         }
235 }
236
237 bAction *BL_Action::GetAction()
238 {
239         return (IsDone()) ? NULL : m_action;
240 }
241
242 float BL_Action::GetFrame()
243 {
244         return m_localtime;
245 }
246
247 void BL_Action::SetFrame(float frame)
248 {
249         // Clamp the frame to the start and end frame
250         if (frame < min(m_startframe, m_endframe))
251                 frame = min(m_startframe, m_endframe);
252         else if (frame > max(m_startframe, m_endframe))
253                 frame = max(m_startframe, m_endframe);
254         
255         m_localtime = frame;
256         m_calc_localtime = false;
257 }
258
259 void BL_Action::SetPlayMode(short play_mode)
260 {
261         m_playmode = play_mode;
262 }
263
264 void BL_Action::SetTimes(float start, float end)
265 {
266         m_startframe = start;
267         m_endframe = end;
268 }
269
270 void BL_Action::SetLocalTime(float curtime)
271 {
272         float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate()*m_speed;
273
274         if (m_endframe < m_startframe)
275                 dt = -dt;
276
277         m_localtime = m_startframe + dt;
278 }
279
280 void BL_Action::ResetStartTime(float curtime)
281 {
282         float dt = (m_localtime > m_startframe) ? m_localtime - m_startframe : m_startframe - m_localtime;
283
284         m_starttime = curtime - dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed);
285         SetLocalTime(curtime);
286 }
287
288 void BL_Action::IncrementBlending(float curtime)
289 {
290         // Setup m_blendstart if we need to
291         if (m_blendstart == 0.f)
292                 m_blendstart = curtime;
293         
294         // Bump the blend frame
295         m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
296
297         // Clamp
298         if (m_blendframe>m_blendin)
299                 m_blendframe = m_blendin;
300 }
301
302
303 void BL_Action::BlendShape(Key* key, float srcweight, std::vector<float>& blendshape)
304 {
305         vector<float>::const_iterator it;
306         float dstweight;
307         KeyBlock *kb;
308         
309         dstweight = 1.0F - srcweight;
310         //printf("Dst: %f\tSrc: %f\n", srcweight, dstweight);
311         for (it=blendshape.begin(), kb = (KeyBlock*)key->block.first; 
312              kb && it != blendshape.end();
313              kb = (KeyBlock*)kb->next, it++)
314         {
315                 //printf("OirgKeys: %f\t%f\n", kb->curval, (*it));
316                 kb->curval = kb->curval * dstweight + (*it) * srcweight;
317                 //printf("NewKey: %f\n", kb->curval);
318         }
319         //printf("\n");
320 }
321
322 void BL_Action::Update(float curtime)
323 {
324         // Don't bother if we're done with the animation
325         if (m_done)
326                 return;
327
328         curtime -= KX_KetsjiEngine::GetSuspendedDelta();
329
330         if (m_calc_localtime)
331                 SetLocalTime(curtime);
332         else
333         {
334                 ResetStartTime(curtime);
335                 m_calc_localtime = true;
336         }
337
338         // Handle wrap around
339         if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe))
340         {
341                 switch(m_playmode)
342                 {
343                 case ACT_MODE_PLAY:
344                         // Clamp
345                         m_localtime = m_endframe;
346                         m_done = true;
347                         break;
348                 case ACT_MODE_LOOP:
349                         // Put the time back to the beginning
350                         m_localtime = m_startframe;
351                         m_starttime = curtime;
352                         break;
353                 case ACT_MODE_PING_PONG:
354                         // Swap the start and end frames
355                         float temp = m_startframe;
356                         m_startframe = m_endframe;
357                         m_endframe = temp;
358
359                         m_starttime = curtime;
360
361                         break;
362                 }
363         }
364
365         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
366         {
367                 BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
368                 obj->GetPose(&m_pose);
369
370                 // Extract the pose from the action
371                 {
372                         Object *arm = obj->GetArmatureObject();
373                         bPose *temp = arm->pose;
374
375                         arm->pose = m_pose;
376                         animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime);
377
378                         arm->pose = temp;
379                 }
380
381                 // Handle blending between armature actions
382                 if (m_blendin && m_blendframe<m_blendin)
383                 {
384                         IncrementBlending(curtime);
385
386                         // Calculate weight
387                         float weight = 1.f - (m_blendframe/m_blendin);
388
389                         // Blend the poses
390                         game_blend_poses(m_pose, m_blendinpose, weight);
391                 }
392
393
394                 // Handle layer blending
395                 if (m_layer_weight >= 0)
396                 {
397                         obj->GetMRDPose(&m_blendpose);
398                         game_blend_poses(m_pose, m_blendpose, m_layer_weight);
399                 }
400
401                 obj->SetPose(m_pose);
402
403                 obj->SetActiveAction(NULL, 0, curtime);
404         }
405         else
406         {
407                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
408                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
409
410                 // Handle shape actions if we have any
411                 if (shape_deformer && shape_deformer->GetKey())
412                 {
413                         Key *key = shape_deformer->GetKey();
414
415
416                         animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime);
417
418                         // Handle blending between shape actions
419                         if (m_blendin && m_blendframe < m_blendin)
420                         {
421                                 IncrementBlending(curtime);
422
423                                 float weight = 1.f - (m_blendframe/m_blendin);
424
425                                 // We go through and clear out the keyblocks so there isn't any interference
426                                 // from other shape actions
427                                 KeyBlock *kb;
428                                 for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next)
429                                         kb->curval = 0.f;
430
431                                 // Now blend the shape
432                                 BlendShape(key, weight, m_blendinshape);
433                         }
434
435                         // Handle layer blending
436                         if (m_layer_weight >= 0)
437                         {
438                                 obj->GetShape(m_blendshape);
439                                 BlendShape(key, m_layer_weight, m_blendshape);
440                         }
441
442                         obj->SetActiveAction(NULL, 0, curtime);
443                 }
444
445                 m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD);
446         }
447 }