ActionActuator in the game engine working again to display deformed meshes with the...
[blender.git] / source / gameengine / Converter / BL_ArmatureObject.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include "BL_ArmatureObject.h"
31 #include "BL_ActionActuator.h"
32 #include "BLI_blenlib.h"
33 #include "BKE_action.h"
34 #include "BKE_armature.h"
35 #include "GEN_Map.h"
36 #include "GEN_HashedPtr.h"
37 #include "MEM_guardedalloc.h"
38 #include "DNA_action_types.h"
39 #include "DNA_armature_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_scene_types.h"
42
43 #include "MT_Matrix4x4.h"
44
45 #ifdef HAVE_CONFIG_H
46 #include <config.h>
47 #endif
48
49 BL_ArmatureObject::BL_ArmatureObject(
50                                 void* sgReplicationInfo, 
51                                 SG_Callbacks callbacks, 
52                                 Object *armature,
53                                 Scene *scene)
54
55 :       KX_GameObject(sgReplicationInfo,callbacks),
56         m_objArma(armature),
57         m_scene(scene), // maybe remove later. needed for where_is_pose
58         m_framePose(NULL),
59         m_lastframe(0.0),
60         m_activeAct(NULL),
61         m_activePriority(999),
62         m_lastapplyframe(0.0)
63 {
64         m_armature = (bArmature *)armature->data;
65
66         /* we make a copy of blender object's pose, and then always swap it with
67          * the original pose before calling into blender functions, to deal with
68          * replica's or other objects using the same blender object */
69         m_pose = NULL;
70         game_copy_pose(&m_pose, m_objArma->pose);
71 }
72
73 CValue* BL_ArmatureObject::GetReplica()
74 {
75         BL_ArmatureObject* replica = new BL_ArmatureObject(*this);
76         replica->ProcessReplica();
77         return replica;
78 }
79
80 void BL_ArmatureObject::ProcessReplica()
81 {
82         bPose *pose= m_pose;
83         KX_GameObject::ProcessReplica();
84
85         m_pose = NULL;
86         game_copy_pose(&m_pose, pose);
87 }
88
89 BL_ArmatureObject::~BL_ArmatureObject()
90 {
91         if (m_pose)
92                 game_free_pose(m_pose);
93 }
94
95 void BL_ArmatureObject::ApplyPose()
96 {
97         m_armpose = m_objArma->pose;
98         m_objArma->pose = m_pose;
99         //m_scene->r.cfra++;
100         if(m_lastapplyframe != m_lastframe) {
101                 where_is_pose(m_scene, m_objArma); // XXX
102                 m_lastapplyframe = m_lastframe;
103         }
104 }
105
106 void BL_ArmatureObject::RestorePose()
107 {
108         m_objArma->pose = m_armpose;
109         m_armpose = NULL;
110 }
111
112 void BL_ArmatureObject::SetPose(bPose *pose)
113 {
114         extract_pose_from_pose(m_pose, pose);
115         m_lastapplyframe = -1.0;
116 }
117
118 bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority, double curtime)
119 {
120         if (curtime != m_lastframe){
121                 m_activePriority = 9999;
122                 m_lastframe= curtime;
123                 m_activeAct = NULL;
124                 // remember the pose at the start of the frame
125                 m_framePose = m_pose;
126         }
127
128         if (priority<=m_activePriority)
129         {
130                 if (priority<m_activePriority)
131                         // this action overwrites the previous ones, start from initial pose to cancel their effects
132                         m_pose = m_framePose;
133                 if (m_activeAct && (m_activeAct!=act))
134                         m_activeAct->SetBlendTime(0.0); /* Reset the blend timer */
135                 m_activeAct = act;
136                 m_activePriority = priority;
137                 m_lastframe = curtime;
138         
139                 return true;
140         }
141         else{
142                 act->SetBlendTime(0.0);
143                 return false;
144         }
145         
146 }
147
148 BL_ActionActuator * BL_ArmatureObject::GetActiveAction()
149 {
150         return m_activeAct;
151 }
152
153 void BL_ArmatureObject::GetPose(bPose **pose)
154 {
155         /* If the caller supplies a null pose, create a new one. */
156         /* Otherwise, copy the armature's pose channels into the caller-supplied pose */
157                 
158         if (!*pose) {
159                 /*      probably not to good of an idea to
160                         duplicate everying, but it clears up 
161                         a crash and memory leakage when 
162                         &BL_ActionActuator::m_pose is freed
163                 */
164                 game_copy_pose(pose, m_pose);
165         }
166         else {
167                 if (*pose == m_pose)
168                         // no need to copy if the pointers are the same
169                         return;
170
171                 extract_pose_from_pose(*pose, m_pose);
172         }
173 }
174
175 void BL_ArmatureObject::GetMRDPose(bPose **pose)
176 {
177         /* If the caller supplies a null pose, create a new one. */
178         /* Otherwise, copy the armature's pose channels into the caller-supplied pose */
179
180         if (!*pose)
181                 game_copy_pose(pose, m_pose);
182         else
183                 extract_pose_from_pose(*pose, m_pose);
184 }
185
186 short BL_ArmatureObject::GetActivePriority()
187 {
188         return m_activePriority;
189 }
190
191 double BL_ArmatureObject::GetLastFrame()
192 {
193         return m_lastframe;
194 }
195
196 bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix)
197 {
198         bPoseChannel *pchan;
199
200         ApplyPose();
201         pchan = get_pose_channel(m_objArma->pose, bone->name);
202         if(pchan)
203                 matrix.setValue(&pchan->pose_mat[0][0]);
204         RestorePose();
205
206         return (pchan != NULL);
207 }
208
209 float BL_ArmatureObject::GetBoneLength(Bone* bone) const
210 {
211         return (float)(MT_Point3(bone->head) - MT_Point3(bone->tail)).length();
212 }