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