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