ActionActuator in the game engine working again to display deformed meshes with the...
[blender-staging.git] / source / gameengine / Converter / BL_ArmatureObject.cpp
index 0c0034bb4af0692b1911f92a12286402937cf8df..f8a9b1b637ffdae6ad4481ef37fb9b83be30b20b 100644 (file)
@@ -1,15 +1,12 @@
 /**
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,7 +24,7 @@
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 #include "BL_ArmatureObject.h"
@@ -41,6 +38,7 @@
 #include "DNA_action_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_object_types.h"
+#include "DNA_scene_types.h"
 
 #include "MT_Matrix4x4.h"
 
 #include <config.h>
 #endif
 
+BL_ArmatureObject::BL_ArmatureObject(
+                               void* sgReplicationInfo, 
+                               SG_Callbacks callbacks, 
+                               Object *armature,
+                               Scene *scene)
+
+:      KX_GameObject(sgReplicationInfo,callbacks),
+       m_objArma(armature),
+       m_scene(scene), // maybe remove later. needed for where_is_pose
+       m_framePose(NULL),
+       m_lastframe(0.0),
+       m_activeAct(NULL),
+       m_activePriority(999),
+       m_lastapplyframe(0.0)
+{
+       m_armature = (bArmature *)armature->data;
+
+       /* we make a copy of blender object's pose, and then always swap it with
+        * the original pose before calling into blender functions, to deal with
+        * replica's or other objects using the same blender object */
+       m_pose = NULL;
+       game_copy_pose(&m_pose, m_objArma->pose);
+}
+
 CValue* BL_ArmatureObject::GetReplica()
 {
        BL_ArmatureObject* replica = new BL_ArmatureObject(*this);
-       
-       // this will copy properties and so on...
-       CValue::AddDataToReplica(replica);
-
-       ProcessReplica(replica);
+       replica->ProcessReplica();
        return replica;
 }
 
-void BL_ArmatureObject::ProcessReplica(BL_ArmatureObject *replica)
+void BL_ArmatureObject::ProcessReplica()
 {
-       KX_GameObject::ProcessReplica(replica);
+       bPose *pose= m_pose;
+       KX_GameObject::ProcessReplica();
 
+       m_pose = NULL;
+       game_copy_pose(&m_pose, pose);
 }
 
 BL_ArmatureObject::~BL_ArmatureObject()
 {
-       if (m_mrdPose){
-//             clear_pose(m_mrdPose);
-               MEM_freeN(m_mrdPose);
-       }
+       if (m_pose)
+               game_free_pose(m_pose);
 }
 
 void BL_ArmatureObject::ApplyPose()
 {
-       if (m_pose){
-//             apply_pose_armature(GetArmature(), m_pose, 1);
-               if (!m_mrdPose)
-                       copy_pose (&m_mrdPose, m_pose, 0);
-               else
-                       extract_pose_from_pose(m_mrdPose, m_pose);
+       m_armpose = m_objArma->pose;
+       m_objArma->pose = m_pose;
+       //m_scene->r.cfra++;
+       if(m_lastapplyframe != m_lastframe) {
+               where_is_pose(m_scene, m_objArma); // XXX
+               m_lastapplyframe = m_lastframe;
        }
 }
 
+void BL_ArmatureObject::RestorePose()
+{
+       m_objArma->pose = m_armpose;
+       m_armpose = NULL;
+}
+
 void BL_ArmatureObject::SetPose(bPose *pose)
 {
-       m_pose = pose;
+       extract_pose_from_pose(m_pose, pose);
+       m_lastapplyframe = -1.0;
 }
 
 bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority, double curtime)
@@ -95,10 +121,15 @@ bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority,
                m_activePriority = 9999;
                m_lastframe= curtime;
                m_activeAct = NULL;
+               // remember the pose at the start of the frame
+               m_framePose = m_pose;
        }
 
        if (priority<=m_activePriority)
        {
+               if (priority<m_activePriority)
+                       // this action overwrites the previous ones, start from initial pose to cancel their effects
+                       m_pose = m_framePose;
                if (m_activeAct && (m_activeAct!=act))
                        m_activeAct->SetBlendTime(0.0); /* Reset the blend timer */
                m_activeAct = act;
@@ -123,11 +154,22 @@ void BL_ArmatureObject::GetPose(bPose **pose)
 {
        /* If the caller supplies a null pose, create a new one. */
        /* Otherwise, copy the armature's pose channels into the caller-supplied pose */
-       if (!*pose)
-               copy_pose(pose, m_pose, 0);
-       else
-               extract_pose_from_pose(*pose, m_pose);
+               
+       if (!*pose) {
+               /*      probably not to good of an idea to
+                       duplicate everying, but it clears up 
+                       a crash and memory leakage when 
+                       &BL_ActionActuator::m_pose is freed
+               */
+               game_copy_pose(pose, m_pose);
+       }
+       else {
+               if (*pose == m_pose)
+                       // no need to copy if the pointers are the same
+                       return;
 
+               extract_pose_from_pose(*pose, m_pose);
+       }
 }
 
 void BL_ArmatureObject::GetMRDPose(bPose **pose)
@@ -135,15 +177,10 @@ void BL_ArmatureObject::GetMRDPose(bPose **pose)
        /* If the caller supplies a null pose, create a new one. */
        /* Otherwise, copy the armature's pose channels into the caller-supplied pose */
 
-       if (!m_mrdPose){
-               copy_pose (&m_mrdPose, m_pose, 0);
-       }
-
        if (!*pose)
-               copy_pose(pose, m_mrdPose, 0);
+               game_copy_pose(pose, m_pose);
        else
-               extract_pose_from_pose(*pose, m_mrdPose);
-
+               extract_pose_from_pose(*pose, m_pose);
 }
 
 short BL_ArmatureObject::GetActivePriority()
@@ -156,23 +193,20 @@ double BL_ArmatureObject::GetLastFrame()
        return m_lastframe;
 }
 
-bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const
+bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix)
 {
-       // ton hack
-       bPoseChannel *pchan= get_pose_channel(m_pose, bone->name);
-       
-//     MT_assert(verify_boneptr((bArmature*) GetArmature(), bone) && "Bone is not part of this armature.");
-       
-       matrix.setValue(&pchan->pose_mat[0][0]);
-       
-       return true;
+       bPoseChannel *pchan;
+
+       ApplyPose();
+       pchan = get_pose_channel(m_objArma->pose, bone->name);
+       if(pchan)
+               matrix.setValue(&pchan->pose_mat[0][0]);
+       RestorePose();
+
+       return (pchan != NULL);
 }
 
 float BL_ArmatureObject::GetBoneLength(Bone* bone) const
 {
-//     MT_assert(verify_boneptr((bArmature*) GetArmature(), bone) && "Bone is not part of this armature.");
-       
-       return (MT_Point3(bone->head) - MT_Point3(bone->tail)).length();
+       return (float)(MT_Point3(bone->head) - MT_Point3(bone->tail)).length();
 }
-
-