Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/gameengine/Converter')
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.cpp10
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.h5
-rw-r--r--source/gameengine/Converter/BL_ArmatureActuator.cpp267
-rw-r--r--source/gameengine/Converter/BL_ArmatureActuator.h93
-rw-r--r--source/gameengine/Converter/BL_ArmatureChannel.cpp469
-rw-r--r--source/gameengine/Converter/BL_ArmatureChannel.h95
-rw-r--r--source/gameengine/Converter/BL_ArmatureConstraint.cpp454
-rw-r--r--source/gameengine/Converter/BL_ArmatureConstraint.h118
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp496
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.h57
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp17
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.h1
-rw-r--r--source/gameengine/Converter/BL_ShapeActionActuator.cpp4
-rw-r--r--source/gameengine/Converter/BL_ShapeActionActuator.h6
-rw-r--r--source/gameengine/Converter/CMakeLists.txt8
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.cpp9
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.h4
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp10
-rw-r--r--source/gameengine/Converter/KX_ConvertControllers.cpp16
-rw-r--r--source/gameengine/Converter/KX_ConvertControllers.h3
-rw-r--r--source/gameengine/Converter/KX_ConvertProperties.cpp3
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.cpp27
-rw-r--r--source/gameengine/Converter/Makefile1
-rw-r--r--source/gameengine/Converter/SConscript13
24 files changed, 2125 insertions, 61 deletions
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index ca4290703e1..6f3036d8e09 100644
--- a/source/gameengine/Converter/BL_ActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -432,6 +432,8 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
return keepgoing;
};
+#ifndef DISABLE_PYTHON
+
/* ------------------------------------------------------------------------- */
/* Python functions */
/* ------------------------------------------------------------------------- */
@@ -526,12 +528,11 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel,
mat.setValue((const float *)matrix);
BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
- obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
if (!m_userpose) {
if(!m_pose)
obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
- game_copy_pose(&m_userpose, m_pose);
+ game_copy_pose(&m_userpose, m_pose, 0);
}
// pchan= verify_pose_channel(m_userpose, string); // adds the channel if its not there.
pchan= get_pose_channel(m_userpose, string); // adds the channel if its not there.
@@ -554,7 +555,7 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel,
if (!m_userpose) {
if(!m_pose)
obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
- game_copy_pose(&m_userpose, m_pose);
+ game_copy_pose(&m_userpose, m_pose, 0);
}
// pchan= verify_pose_channel(m_userpose, string);
pchan= get_pose_channel(m_userpose, string); // adds the channel if its not there.
@@ -572,7 +573,6 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel,
return NULL;
}
- pchan->flag |= POSE_ROT|POSE_LOC|POSE_SIZE;
Py_RETURN_NONE;
}
@@ -677,3 +677,5 @@ PyObject* BL_ActionActuator::pyattr_get_channel_names(void *self_v, const KX_PYA
return ret;
}
+
+#endif // DISABLE_PYTHON
diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h
index a6b4c4a055d..3f3cd5f496d 100644
--- a/source/gameengine/Converter/BL_ActionActuator.h
+++ b/source/gameengine/Converter/BL_ActionActuator.h
@@ -50,7 +50,7 @@ public:
short priority,
short end_reset,
float stride)
- : SCA_IActuator(gameobj),
+ : SCA_IActuator(gameobj, KX_ACT_ACTION),
m_lastpos(0, 0, 0),
m_blendframe(0),
@@ -84,6 +84,8 @@ public:
bAction* GetAction() { return m_action; }
void SetAction(bAction* act) { m_action= act; }
+#ifndef DISABLE_PYTHON
+
KX_PYMETHOD_O(BL_ActionActuator,GetChannel);
KX_PYMETHOD_DOC(BL_ActionActuator,setChannel);
@@ -129,6 +131,7 @@ public:
return 1;
}
}
+#endif // DISABLE_PYTHON
protected:
diff --git a/source/gameengine/Converter/BL_ArmatureActuator.cpp b/source/gameengine/Converter/BL_ArmatureActuator.cpp
new file mode 100644
index 00000000000..a018f0f938d
--- /dev/null
+++ b/source/gameengine/Converter/BL_ArmatureActuator.cpp
@@ -0,0 +1,267 @@
+/**
+ * $Id$
+ *
+ * ***** 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "DNA_action_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_actuator_types.h"
+#include "BKE_constraint.h"
+#include "BLI_arithb.h"
+#include "BL_ArmatureActuator.h"
+#include "BL_ArmatureObject.h"
+
+/**
+ * This class is the conversion of the Pose channel constraint.
+ * It makes a link between the pose constraint and the KX scene.
+ * The main purpose is to give access to the constraint target
+ * to link it to a game object.
+ * It also allows to activate/deactivate constraints during the game.
+ * Later it will also be possible to create constraint on the fly
+ */
+
+BL_ArmatureActuator::BL_ArmatureActuator(SCA_IObject* obj,
+ int type,
+ const char *posechannel,
+ const char *constraintname,
+ KX_GameObject* targetobj,
+ KX_GameObject* subtargetobj,
+ float weight) :
+ SCA_IActuator(obj, KX_ACT_ARMATURE),
+ m_constraint(NULL),
+ m_gametarget(targetobj),
+ m_gamesubtarget(subtargetobj),
+ m_posechannel(posechannel),
+ m_constraintname(constraintname),
+ m_weight(weight),
+ m_type(type)
+{
+ if (m_gametarget)
+ m_gametarget->RegisterActuator(this);
+ if (m_gamesubtarget)
+ m_gamesubtarget->RegisterActuator(this);
+ FindConstraint();
+}
+
+BL_ArmatureActuator::~BL_ArmatureActuator()
+{
+ if (m_gametarget)
+ m_gametarget->UnregisterActuator(this);
+ if (m_gamesubtarget)
+ m_gamesubtarget->UnregisterActuator(this);
+}
+
+void BL_ArmatureActuator::ProcessReplica()
+{
+ // the replica is tracking the same object => register it (this may be changed in Relnk())
+ if (m_gametarget)
+ m_gametarget->RegisterActuator(this);
+ if (m_gamesubtarget)
+ m_gamesubtarget->UnregisterActuator(this);
+ SCA_IActuator::ProcessReplica();
+}
+
+void BL_ArmatureActuator::ReParent(SCA_IObject* parent)
+{
+ SCA_IActuator::ReParent(parent);
+ // must remap the constraint
+ FindConstraint();
+}
+
+bool BL_ArmatureActuator::UnlinkObject(SCA_IObject* clientobj)
+{
+ bool res=false;
+ if (clientobj == m_gametarget)
+ {
+ // this object is being deleted, we cannot continue to track it.
+ m_gametarget = NULL;
+ res = true;
+ }
+ if (clientobj == m_gamesubtarget)
+ {
+ // this object is being deleted, we cannot continue to track it.
+ m_gamesubtarget = NULL;
+ res = true;
+ }
+ return res;
+}
+
+void BL_ArmatureActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
+{
+ void **h_obj = (*obj_map)[m_gametarget];
+ if (h_obj) {
+ if (m_gametarget)
+ m_gametarget->UnregisterActuator(this);
+ m_gametarget = (KX_GameObject*)(*h_obj);
+ m_gametarget->RegisterActuator(this);
+ }
+ h_obj = (*obj_map)[m_gamesubtarget];
+ if (h_obj) {
+ if (m_gamesubtarget)
+ m_gamesubtarget->UnregisterActuator(this);
+ m_gamesubtarget = (KX_GameObject*)(*h_obj);
+ m_gamesubtarget->RegisterActuator(this);
+ }
+}
+
+void BL_ArmatureActuator::FindConstraint()
+{
+ m_constraint = NULL;
+
+ if (m_gameobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) {
+ BL_ArmatureObject* armobj = (BL_ArmatureObject*)m_gameobj;
+ m_constraint = armobj->GetConstraint(m_posechannel, m_constraintname);
+ }
+}
+
+bool BL_ArmatureActuator::Update(double curtime, bool frame)
+{
+ // the only role of this actuator is to ensure that the armature pose will be evaluated
+ bool result = false;
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+ if (!bNegativeEvent) {
+ BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
+ switch (m_type) {
+ case ACT_ARM_RUN:
+ result = true;
+ obj->SetActiveAction(NULL, 0, curtime);
+ break;
+ case ACT_ARM_ENABLE:
+ if (m_constraint)
+ m_constraint->ClrConstraintFlag(CONSTRAINT_OFF);
+ break;
+ case ACT_ARM_DISABLE:
+ if (m_constraint)
+ m_constraint->SetConstraintFlag(CONSTRAINT_OFF);
+ break;
+ case ACT_ARM_SETTARGET:
+ if (m_constraint) {
+ m_constraint->SetTarget(m_gametarget);
+ m_constraint->SetSubtarget(m_gamesubtarget);
+ }
+ break;
+ case ACT_ARM_SETWEIGHT:
+ if (m_constraint)
+ m_constraint->SetWeight(m_weight);
+ break;
+ }
+ }
+ return result;
+}
+
+#ifndef DISABLE_PYTHON
+
+/* ------------------------------------------------------------------------- */
+/* Python Integration Hooks */
+/* ------------------------------------------------------------------------- */
+
+PyTypeObject BL_ArmatureActuator::Type = {
+#if (PY_VERSION_HEX >= 0x02060000)
+ PyVarObject_HEAD_INIT(NULL, 0)
+#else
+ /* python 2.5 and below */
+ PyObject_HEAD_INIT( NULL ) /* required py macro */
+ 0, /* ob_size */
+#endif
+ "BL_ArmatureActuator",
+ sizeof(PyObjectPlus_Proxy),
+ 0,
+ py_base_dealloc,
+ 0,
+ 0,
+ 0,
+ 0,
+ py_base_repr,
+ 0,0,0,0,0,0,0,0,0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ 0,0,0,0,0,0,0,
+ Methods,
+ 0,
+ 0,
+ &SCA_IActuator::Type,
+ 0,0,0,0,0,0,
+ py_base_new
+};
+
+
+PyMethodDef BL_ArmatureActuator::Methods[] = {
+ {NULL,NULL} //Sentinel
+};
+
+PyAttributeDef BL_ArmatureActuator::Attributes[] = {
+ KX_PYATTRIBUTE_RO_FUNCTION("constraint", BL_ArmatureActuator, pyattr_get_constraint),
+ KX_PYATTRIBUTE_RW_FUNCTION("target", BL_ArmatureActuator, pyattr_get_object, pyattr_set_object),
+ KX_PYATTRIBUTE_RW_FUNCTION("subtarget", BL_ArmatureActuator, pyattr_get_object, pyattr_set_object),
+ KX_PYATTRIBUTE_FLOAT_RW("weight",0.0f,1.0f,BL_ArmatureActuator,m_weight),
+ KX_PYATTRIBUTE_INT_RW("type",0,ACT_ARM_MAXTYPE,false,BL_ArmatureActuator,m_type),
+ { NULL } //Sentinel
+};
+
+PyObject* BL_ArmatureActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+{
+ BL_ArmatureActuator* actuator = static_cast<BL_ArmatureActuator*>(self);
+ KX_GameObject *target = (!strcmp(attrdef->m_name, "target")) ? actuator->m_gametarget : actuator->m_gamesubtarget;
+ if (!target)
+ Py_RETURN_NONE;
+ else
+ return target->GetProxy();
+}
+
+int BL_ArmatureActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ BL_ArmatureActuator* actuator = static_cast<BL_ArmatureActuator*>(self);
+ KX_GameObject* &target = (!strcmp(attrdef->m_name, "target")) ? actuator->m_gametarget : actuator->m_gamesubtarget;
+ KX_GameObject *gameobj;
+
+ if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: BL_ArmatureActuator"))
+ return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
+
+ if (target != NULL)
+ target->UnregisterActuator(actuator);
+
+ target = gameobj;
+
+ if (target)
+ target->RegisterActuator(actuator);
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject* BL_ArmatureActuator::pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+{
+ BL_ArmatureActuator* actuator = static_cast<BL_ArmatureActuator*>(self);
+ BL_ArmatureConstraint* constraint = actuator->m_constraint;
+ if (!constraint)
+ Py_RETURN_NONE;
+ else
+ return constraint->GetProxy();
+}
+
+#endif // DISABLE_PYTHON
+
diff --git a/source/gameengine/Converter/BL_ArmatureActuator.h b/source/gameengine/Converter/BL_ArmatureActuator.h
new file mode 100644
index 00000000000..e7e12bc2e4e
--- /dev/null
+++ b/source/gameengine/Converter/BL_ArmatureActuator.h
@@ -0,0 +1,93 @@
+/**
+ * $Id$
+ *
+ * ***** 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef BL_ARMATUREACTUATOR
+#define BL_ARMATUREACTUATOR
+
+#include "SCA_IActuator.h"
+#include "BL_ArmatureConstraint.h"
+
+/**
+ * This class is the conversion of the Pose channel constraint.
+ * It makes a link between the pose constraint and the KX scene.
+ * The main purpose is to give access to the constraint target
+ * to link it to a game object.
+ * It also allows to activate/deactivate constraints during the game.
+ * Later it will also be possible to create constraint on the fly
+ */
+
+class BL_ArmatureActuator : public SCA_IActuator
+{
+ Py_Header;
+public:
+ BL_ArmatureActuator(SCA_IObject* gameobj,
+ int type,
+ const char *posechannel,
+ const char *constraintname,
+ KX_GameObject* targetobj,
+ KX_GameObject* subtargetobj,
+ float weight);
+
+ virtual ~BL_ArmatureActuator();
+
+ virtual CValue* GetReplica() {
+ BL_ArmatureActuator* replica = new BL_ArmatureActuator(*this);
+ replica->ProcessReplica();
+ return replica;
+ };
+ virtual void ProcessReplica();
+ virtual bool UnlinkObject(SCA_IObject* clientobj);
+ virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
+ virtual bool Update(double curtime, bool frame);
+ virtual void ReParent(SCA_IObject* parent);
+
+#ifndef DISABLE_PYTHON
+
+ /* These are used to get and set m_target */
+ static PyObject* pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+
+#endif // DISABLE_PYTHON
+
+private:
+ // identify the constraint that this actuator controls
+ void FindConstraint();
+
+ BL_ArmatureConstraint* m_constraint;
+ KX_GameObject* m_gametarget;
+ KX_GameObject* m_gamesubtarget;
+ STR_String m_posechannel;
+ STR_String m_constraintname;
+ float m_weight;
+ int m_type;
+};
+
+#endif //BL_ARMATUREACTUATOR
+
+
diff --git a/source/gameengine/Converter/BL_ArmatureChannel.cpp b/source/gameengine/Converter/BL_ArmatureChannel.cpp
new file mode 100644
index 00000000000..9a9161b080f
--- /dev/null
+++ b/source/gameengine/Converter/BL_ArmatureChannel.cpp
@@ -0,0 +1,469 @@
+/**
+ * $Id$
+ * ***** 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "DNA_armature_types.h"
+#include "BL_ArmatureChannel.h"
+#include "BL_ArmatureObject.h"
+#include "BL_ArmatureConstraint.h"
+#include "BLI_arithb.h"
+#include "BLI_string.h"
+
+#ifndef DISABLE_PYTHON
+
+PyTypeObject BL_ArmatureChannel::Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BL_ArmatureChannel",
+ sizeof(PyObjectPlus_Proxy),
+ 0,
+ py_base_dealloc,
+ 0,
+ 0,
+ 0,
+ 0,
+ py_base_repr,
+ 0,0,0,0,0,0,0,0,0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ 0,0,0,0,0,0,0,
+ Methods,
+ 0,
+ 0,
+ &CValue::Type,
+ 0,0,0,0,0,0,
+ py_base_new
+};
+
+PyObject* BL_ArmatureChannel::py_repr(void)
+{
+ return PyUnicode_FromString(m_posechannel->name);
+}
+
+PyObject *BL_ArmatureChannel::GetProxy()
+{
+ return GetProxyPlus_Ext(this, &Type, m_posechannel);
+}
+
+PyObject *BL_ArmatureChannel::NewProxy(bool py_owns)
+{
+ return NewProxyPlus_Ext(this, &Type, m_posechannel, py_owns);
+}
+
+#endif // DISABLE_PYTHON
+
+BL_ArmatureChannel::BL_ArmatureChannel(
+ BL_ArmatureObject *armature,
+ bPoseChannel *posechannel)
+ : PyObjectPlus(), m_posechannel(posechannel), m_armature(armature)
+{
+}
+
+BL_ArmatureChannel::~BL_ArmatureChannel()
+{
+}
+
+#ifndef DISABLE_PYTHON
+
+// PYTHON
+
+PyMethodDef BL_ArmatureChannel::Methods[] = {
+ {NULL,NULL} //Sentinel
+};
+
+// order of definition of attributes, must match Attributes[] array
+#define BCA_BONE 0
+#define BCA_PARENT 1
+
+PyAttributeDef BL_ArmatureChannel::Attributes[] = {
+ // Keep these attributes in order of BCA_ defines!!! used by py_attr_getattr and py_attr_setattr
+ KX_PYATTRIBUTE_RO_FUNCTION("bone",BL_ArmatureChannel,py_attr_getattr),
+ KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureChannel,py_attr_getattr),
+
+ { NULL } //Sentinel
+};
+
+/* attributes directly taken from bPoseChannel */
+PyAttributeDef BL_ArmatureChannel::AttributesPtr[] = {
+ KX_PYATTRIBUTE_CHAR_RO("name",bPoseChannel,name),
+ KX_PYATTRIBUTE_FLAG_RO("has_ik",bPoseChannel,flag, POSE_CHAIN),
+ KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_x",bPoseChannel,ikflag, BONE_IK_NO_XDOF),
+ KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_y",bPoseChannel,ikflag, BONE_IK_NO_YDOF),
+ KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_z",bPoseChannel,ikflag, BONE_IK_NO_ZDOF),
+ KX_PYATTRIBUTE_FLAG_RO("ik_limit_x",bPoseChannel,ikflag, BONE_IK_XLIMIT),
+ KX_PYATTRIBUTE_FLAG_RO("ik_limit_y",bPoseChannel,ikflag, BONE_IK_YLIMIT),
+ KX_PYATTRIBUTE_FLAG_RO("ik_limit_z",bPoseChannel,ikflag, BONE_IK_ZLIMIT),
+ KX_PYATTRIBUTE_FLAG_RO("ik_rot_control",bPoseChannel,ikflag, BONE_IK_ROTCTL),
+ KX_PYATTRIBUTE_FLAG_RO("ik_lin_control",bPoseChannel,ikflag, BONE_IK_LINCTL),
+ KX_PYATTRIBUTE_FLOAT_VECTOR_RW("location",-FLT_MAX,FLT_MAX,bPoseChannel,loc,3),
+ KX_PYATTRIBUTE_FLOAT_VECTOR_RW("scale",-FLT_MAX,FLT_MAX,bPoseChannel,size,3),
+ KX_PYATTRIBUTE_FLOAT_VECTOR_RW("rotation_quaternion",-1.0f,1.0f,bPoseChannel,quat,4),
+ KX_PYATTRIBUTE_FLOAT_VECTOR_RW("rotaion_euler",-10.f,10.f,bPoseChannel,eul,3),
+ KX_PYATTRIBUTE_SHORT_RW("rotation_mode",0,ROT_MODE_MAX-1,false,bPoseChannel,rotmode),
+ KX_PYATTRIBUTE_FLOAT_MATRIX_RO("channel_matrix",bPoseChannel,chan_mat,4),
+ KX_PYATTRIBUTE_FLOAT_MATRIX_RO("pose_matrix",bPoseChannel,pose_mat,4),
+ KX_PYATTRIBUTE_FLOAT_VECTOR_RO("pose_head",bPoseChannel,pose_head,3),
+ KX_PYATTRIBUTE_FLOAT_VECTOR_RO("pose_tail",bPoseChannel,pose_tail,3),
+ KX_PYATTRIBUTE_FLOAT_RO("ik_min_x",bPoseChannel,limitmin[0]),
+ KX_PYATTRIBUTE_FLOAT_RO("ik_max_x",bPoseChannel,limitmax[0]),
+ KX_PYATTRIBUTE_FLOAT_RO("ik_min_y",bPoseChannel,limitmin[1]),
+ KX_PYATTRIBUTE_FLOAT_RO("ik_max_y",bPoseChannel,limitmax[1]),
+ KX_PYATTRIBUTE_FLOAT_RO("ik_min_z",bPoseChannel,limitmin[2]),
+ KX_PYATTRIBUTE_FLOAT_RO("ik_max_z",bPoseChannel,limitmax[2]),
+ KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_x",bPoseChannel,stiffness[0]),
+ KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_y",bPoseChannel,stiffness[1]),
+ KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_z",bPoseChannel,stiffness[2]),
+ KX_PYATTRIBUTE_FLOAT_RO("ik_stretch",bPoseChannel,ikstretch),
+ KX_PYATTRIBUTE_FLOAT_RW("ik_rot_weight",0,1.0f,bPoseChannel,ikrotweight),
+ KX_PYATTRIBUTE_FLOAT_RW("ik_lin_weight",0,1.0f,bPoseChannel,iklinweight),
+ KX_PYATTRIBUTE_RW_FUNCTION("joint_rotation",BL_ArmatureChannel,py_attr_get_joint_rotation,py_attr_set_joint_rotation),
+ { NULL } //Sentinel
+};
+
+PyObject* BL_ArmatureChannel::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
+{
+ BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v);
+ bPoseChannel* channel = self->m_posechannel;
+ int attr_order = attrdef-Attributes;
+
+ if (!channel) {
+ PyErr_SetString(PyExc_AttributeError, "channel is NULL");
+ return NULL;
+ }
+
+ switch (attr_order) {
+ case BCA_BONE:
+ // bones are standalone proxy
+ return NewProxyPlus_Ext(NULL,&BL_ArmatureBone::Type,channel->bone,false);
+ case BCA_PARENT:
+ {
+ BL_ArmatureChannel* parent = self->m_armature->GetChannel(channel->parent);
+ if (parent)
+ return parent->GetProxy();
+ else
+ Py_RETURN_NONE;
+ }
+ }
+ PyErr_SetString(PyExc_AttributeError, "channel unknown attribute");
+ return NULL;
+}
+
+int BL_ArmatureChannel::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v);
+ bPoseChannel* channel = self->m_posechannel;
+ int attr_order = attrdef-Attributes;
+
+ int ival;
+ double dval;
+ char* sval;
+ KX_GameObject *oval;
+
+ if (!channel) {
+ PyErr_SetString(PyExc_AttributeError, "channel is NULL");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ switch (attr_order) {
+ default:
+ break;
+ }
+
+ PyErr_SetString(PyExc_AttributeError, "channel unknown attribute");
+ return PY_SET_ATTR_FAIL;
+}
+
+PyObject* BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
+{
+ BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v);
+ bPoseChannel* pchan = self->m_posechannel;
+ // decompose the pose matrix in euler rotation
+ float rest_mat[3][3];
+ float pose_mat[3][3];
+ float joint_mat[3][3];
+ float joints[3];
+ float norm;
+ double sa, ca;
+ // get rotation in armature space
+ Mat3CpyMat4(pose_mat, pchan->pose_mat);
+ Mat3Ortho(pose_mat);
+ if (pchan->parent) {
+ // bone has a parent, compute the rest pose of the bone taking actual pose of parent
+ Mat3IsMat3MulMat4(rest_mat, pchan->bone->bone_mat, pchan->parent->pose_mat);
+ Mat3Ortho(rest_mat);
+ } else {
+ // otherwise, the bone matrix in armature space is the rest pose
+ Mat3CpyMat4(rest_mat, pchan->bone->arm_mat);
+ }
+ // remove the rest pose to get the joint movement
+ Mat3Transp(rest_mat);
+ Mat3MulMat3(joint_mat, rest_mat, pose_mat);
+ joints[0] = joints[1] = joints[2] = 0.f;
+ // returns a 3 element list that gives corresponding joint
+ int flag = 0;
+ if (!(pchan->ikflag & BONE_IK_NO_XDOF))
+ flag |= 1;
+ if (!(pchan->ikflag & BONE_IK_NO_YDOF))
+ flag |= 2;
+ if (!(pchan->ikflag & BONE_IK_NO_ZDOF))
+ flag |= 4;
+ switch (flag) {
+ case 0: // fixed joint
+ break;
+ case 1: // X only
+ Mat3ToEulO(joint_mat, joints, EULER_ORDER_XYZ);
+ joints[1] = joints[2] = 0.f;
+ break;
+ case 2: // Y only
+ Mat3ToEulO(joint_mat, joints, EULER_ORDER_XYZ);
+ joints[0] = joints[2] = 0.f;
+ break;
+ case 3: // X+Y
+ Mat3ToEulO(joint_mat, joints, EULER_ORDER_ZYX);
+ joints[2] = 0.f;
+ break;
+ case 4: // Z only
+ Mat3ToEulO(joint_mat, joints, EULER_ORDER_XYZ);
+ joints[0] = joints[1] = 0.f;
+ break;
+ case 5: // X+Z
+ // decompose this as an equivalent rotation vector in X/Z plane
+ joints[0] = joint_mat[1][2];
+ joints[2] = -joint_mat[1][0];
+ norm = Normalize(joints);
+ if (norm < FLT_EPSILON) {
+ norm = (joint_mat[1][1] < 0.f) ? M_PI : 0.f;
+ } else {
+ norm = acos(joint_mat[1][1]);
+ }
+ VecMulf(joints, norm);
+ break;
+ case 6: // Y+Z
+ Mat3ToEulO(joint_mat, joints, EULER_ORDER_XYZ);
+ joints[0] = 0.f;
+ break;
+ case 7: // X+Y+Z
+ // equivalent axis
+ joints[0] = (joint_mat[1][2]-joint_mat[2][1])*0.5f;
+ joints[1] = (joint_mat[2][0]-joint_mat[0][2])*0.5f;
+ joints[2] = (joint_mat[0][1]-joint_mat[1][0])*0.5f;
+ sa = VecLength(joints);
+ ca = (joint_mat[0][0]+joint_mat[1][1]+joint_mat[1][1]-1.0f)*0.5f;
+ if (sa > FLT_EPSILON) {
+ norm = atan2(sa,ca)/sa;
+ } else {
+ if (ca < 0.0) {
+ norm = M_PI;
+ VecMulf(joints,0.f);
+ if (joint_mat[0][0] > 0.f) {
+ joints[0] = 1.0f;
+ } else if (joint_mat[1][1] > 0.f) {
+ joints[1] = 1.0f;
+ } else {
+ joints[2] = 1.0f;
+ }
+ } else {
+ norm = 0.0;
+ }
+ }
+ VecMulf(joints,norm);
+ break;
+ }
+ return newVectorObject(joints, 3, Py_NEW, NULL);
+}
+
+int BL_ArmatureChannel::py_attr_set_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v);
+ bPoseChannel* pchan = self->m_posechannel;
+ PyObject *item;
+ float joints[3];
+ float quat[4];
+
+ if (!PySequence_Check(value) || PySequence_Size(value) != 3) {
+ PyErr_SetString(PyExc_AttributeError, "expected a sequence of [3] floats");
+ return PY_SET_ATTR_FAIL;
+ }
+ for (int i=0; i<3; i++) {
+ item = PySequence_GetItem(value, i); /* new ref */
+ joints[i] = PyFloat_AsDouble(item);
+ Py_DECREF(item);
+ if (joints[i] == -1.0f && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_AttributeError, "expected a sequence of [3] floats");
+ return PY_SET_ATTR_FAIL;
+ }
+ }
+
+ int flag = 0;
+ if (!(pchan->ikflag & BONE_IK_NO_XDOF))
+ flag |= 1;
+ if (!(pchan->ikflag & BONE_IK_NO_YDOF))
+ flag |= 2;
+ if (!(pchan->ikflag & BONE_IK_NO_ZDOF))
+ flag |= 4;
+ QuatOne(quat);
+ switch (flag) {
+ case 0: // fixed joint
+ break;
+ case 1: // X only
+ joints[1] = joints[2] = 0.f;
+ EulOToQuat(joints, EULER_ORDER_XYZ, quat);
+ break;
+ case 2: // Y only
+ joints[0] = joints[2] = 0.f;
+ EulOToQuat(joints, EULER_ORDER_XYZ, quat);
+ break;
+ case 3: // X+Y
+ joints[2] = 0.f;
+ EulOToQuat(joints, EULER_ORDER_ZYX, quat);
+ break;
+ case 4: // Z only
+ joints[0] = joints[1] = 0.f;
+ EulOToQuat(joints, EULER_ORDER_XYZ, quat);
+ break;
+ case 5: // X+Z
+ // X and Z are components of an equivalent rotation axis
+ joints[1] = 0;
+ VecRotToQuat(joints, VecLength(joints), quat);
+ break;
+ case 6: // Y+Z
+ joints[0] = 0.f;
+ EulOToQuat(joints, EULER_ORDER_XYZ, quat);
+ break;
+ case 7: // X+Y+Z
+ // equivalent axis
+ VecRotToQuat(joints, VecLength(joints), quat);
+ break;
+ }
+ if (pchan->rotmode > 0) {
+ QuatToEulO(quat, joints, pchan->rotmode);
+ VecCopyf(pchan->eul, joints);
+ } else
+ QuatCopy(pchan->quat, quat);
+ return PY_SET_ATTR_SUCCESS;
+}
+
+// *************************
+// BL_ArmatureBone
+//
+// Access to Bone structure
+PyTypeObject BL_ArmatureBone::Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BL_ArmatureBone",
+ sizeof(PyObjectPlus_Proxy),
+ 0,
+ py_base_dealloc,
+ 0,
+ 0,
+ 0,
+ 0,
+ py_bone_repr,
+ 0,0,0,0,0,0,0,0,0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ 0,0,0,0,0,0,0,
+ Methods,
+ 0,
+ 0,
+ &CValue::Type,
+ 0,0,0,0,0,0,
+ py_base_new
+};
+
+// not used since this class is never instantiated
+PyObject *BL_ArmatureBone::GetProxy()
+{
+ return NULL;
+}
+PyObject *BL_ArmatureBone::NewProxy(bool py_owns)
+{
+ return NULL;
+}
+
+PyObject *BL_ArmatureBone::py_bone_repr(PyObject *self)
+{
+ Bone* bone = static_cast<Bone*>BGE_PROXY_PTR(self);
+ return PyUnicode_FromString(bone->name);
+}
+
+PyMethodDef BL_ArmatureBone::Methods[] = {
+ {NULL,NULL} //Sentinel
+};
+
+/* no attributes on C++ class since it is never instantiated */
+PyAttributeDef BL_ArmatureBone::Attributes[] = {
+ { NULL } //Sentinel
+};
+
+// attributes that work on proxy ptr (points to a Bone structure)
+PyAttributeDef BL_ArmatureBone::AttributesPtr[] = {
+ KX_PYATTRIBUTE_CHAR_RO("name",Bone,name),
+ KX_PYATTRIBUTE_FLAG_RO("connected",Bone,flag, BONE_CONNECTED),
+ KX_PYATTRIBUTE_FLAG_RO("hinge",Bone,flag, BONE_HINGE),
+ KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("inherit_scale",Bone,flag, BONE_NO_SCALE),
+ KX_PYATTRIBUTE_SHORT_RO("bbone_segments",Bone,segments),
+ KX_PYATTRIBUTE_FLOAT_RO("roll",Bone,roll),
+ KX_PYATTRIBUTE_FLOAT_VECTOR_RO("head",Bone,head,3),
+ KX_PYATTRIBUTE_FLOAT_VECTOR_RO("tail",Bone,tail,3),
+ KX_PYATTRIBUTE_FLOAT_RO("length",Bone,length),
+ KX_PYATTRIBUTE_FLOAT_VECTOR_RO("arm_head",Bone,arm_head,3),
+ KX_PYATTRIBUTE_FLOAT_VECTOR_RO("arm_tail",Bone,arm_tail,3),
+ KX_PYATTRIBUTE_FLOAT_MATRIX_RO("arm_mat",Bone,arm_mat,4),
+ KX_PYATTRIBUTE_FLOAT_MATRIX_RO("bone_mat",Bone,bone_mat,4),
+ KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureBone,py_bone_get_parent),
+ KX_PYATTRIBUTE_RO_FUNCTION("children",BL_ArmatureBone,py_bone_get_parent),
+ { NULL } //Sentinel
+};
+
+PyObject *BL_ArmatureBone::py_bone_get_parent(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+{
+ Bone* bone = reinterpret_cast<Bone*>BGE_PROXY_PTR(self);
+ if (bone->parent) {
+ // create a proxy unconnected to any GE object
+ return NewProxyPlus_Ext(NULL,&Type,bone->parent,false);
+ }
+ Py_RETURN_NONE;
+}
+
+PyObject *BL_ArmatureBone::py_bone_get_children(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+{
+ Bone* bone = reinterpret_cast<Bone*>BGE_PROXY_PTR(self);
+ Bone* child;
+ int count = 0;
+ for (child=(Bone*)bone->childbase.first; child; child=(Bone*)child->next)
+ count++;
+
+ PyObject* childrenlist = PyList_New(count);
+
+ for (count = 0, child=(Bone*)bone->childbase.first; child; child=(Bone*)child->next, ++count)
+ PyList_SET_ITEM(childrenlist,count,NewProxyPlus_Ext(NULL,&Type,child,false));
+
+ return childrenlist;
+}
+
+#endif // DISABLE_PYTHON
diff --git a/source/gameengine/Converter/BL_ArmatureChannel.h b/source/gameengine/Converter/BL_ArmatureChannel.h
new file mode 100644
index 00000000000..64b03835d83
--- /dev/null
+++ b/source/gameengine/Converter/BL_ArmatureChannel.h
@@ -0,0 +1,95 @@
+/**
+ * $Id$
+ *
+ * ***** 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BL_ARMATURECHANNEL
+#define __BL_ARMATURECHANNEL
+
+#include "DNA_action_types.h"
+#include "GEN_HashedPtr.h"
+#include "GEN_Map.h"
+#include "PyObjectPlus.h"
+
+class SCA_IObject;
+class KX_GameObject;
+class BL_ArmatureObject;
+struct bConstraint;
+struct bPoseChannel;
+struct Object;
+struct bPose;
+
+class BL_ArmatureChannel : public PyObjectPlus
+{
+ // use Py_HeaderPtr since we use generic pointer in proxy
+ Py_HeaderPtr;
+
+private:
+ friend class BL_ArmatureObject;
+ struct bPoseChannel* m_posechannel;
+ BL_ArmatureObject* m_armature;
+
+public:
+ BL_ArmatureChannel(class BL_ArmatureObject *armature,
+ struct bPoseChannel *posechannel);
+ virtual ~BL_ArmatureChannel();
+
+#ifndef DISABLE_PYTHON
+ // Python access
+ virtual PyObject* py_repr(void);
+
+ static PyObject* py_attr_getattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static int py_attr_setattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* py_attr_get_joint_rotation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static int py_attr_set_joint_rotation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+#endif // DISABLE_PYTHON
+};
+
+/* this is a factory class to access bBone data field in the GE.
+ It's not supposed to be instantiated, we only need it for the Attributes and Method array.
+ The actual proxy object will be manually created using NewProxyPtr */
+class BL_ArmatureBone : public PyObjectPlus
+{
+ // use Py_HeaderPtr since we use generic pointer in proxy
+ Py_HeaderPtr;
+private:
+ // make constructor private to make sure no one tries to instantiate this class
+ BL_ArmatureBone() {}
+ virtual ~BL_ArmatureBone() {}
+
+public:
+
+#ifndef DISABLE_PYTHON
+ static PyObject *py_bone_repr(PyObject *self);
+ static PyObject *py_bone_get_parent(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *py_bone_get_children(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+#endif
+
+};
+
+
+#endif //__BL_ARMATURECHANNEL
+
diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.cpp b/source/gameengine/Converter/BL_ArmatureConstraint.cpp
new file mode 100644
index 00000000000..42581b63ec4
--- /dev/null
+++ b/source/gameengine/Converter/BL_ArmatureConstraint.cpp
@@ -0,0 +1,454 @@
+/**
+ * $Id$
+ * ***** 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "DNA_constraint_types.h"
+#include "DNA_action_types.h"
+#include "BL_ArmatureConstraint.h"
+#include "BL_ArmatureObject.h"
+#include "BLI_arithb.h"
+#include "BLI_string.h"
+
+#ifndef DISABLE_PYTHON
+
+PyTypeObject BL_ArmatureConstraint::Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BL_ArmatureConstraint",
+ sizeof(PyObjectPlus_Proxy),
+ 0,
+ py_base_dealloc,
+ 0,
+ 0,
+ 0,
+ 0,
+ py_base_repr,
+ 0,0,0,0,0,0,0,0,0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ 0,0,0,0,0,0,0,
+ Methods,
+ 0,
+ 0,
+ &CValue::Type,
+ 0,0,0,0,0,0,
+ py_base_new
+};
+
+PyObject* BL_ArmatureConstraint::py_repr(void)
+{
+ return PyUnicode_FromString(m_name);
+}
+
+#endif // DISABLE_PYTHON
+
+BL_ArmatureConstraint::BL_ArmatureConstraint(
+ BL_ArmatureObject *armature,
+ bPoseChannel *posechannel,
+ bConstraint *constraint,
+ KX_GameObject* target,
+ KX_GameObject* subtarget)
+ : PyObjectPlus(), m_armature(armature), m_constraint(constraint), m_posechannel(posechannel)
+{
+ m_target = target;
+ m_blendtarget = (target) ? target->GetBlenderObject() : NULL;
+ m_subtarget = subtarget;
+ m_blendsubtarget = (subtarget) ? subtarget->GetBlenderObject() : NULL;
+ m_pose = m_subpose = NULL;
+ if (m_blendtarget) {
+ Mat4CpyMat4(m_blendmat, m_blendtarget->obmat);
+ if (m_blendtarget->type == OB_ARMATURE)
+ m_pose = m_blendtarget->pose;
+ }
+ if (m_blendsubtarget) {
+ Mat4CpyMat4(m_blendsubmat, m_blendsubtarget->obmat);
+ if (m_blendsubtarget->type == OB_ARMATURE)
+ m_subpose = m_blendsubtarget->pose;
+ }
+ if (m_target)
+ m_target->RegisterObject(m_armature);
+ if (m_subtarget)
+ m_subtarget->RegisterObject(m_armature);
+ BLI_snprintf(m_name, sizeof(m_name), "%s:%s", m_posechannel->name, m_constraint->name);
+}
+
+BL_ArmatureConstraint::~BL_ArmatureConstraint()
+{
+ if (m_target)
+ m_target->UnregisterObject(m_armature);
+ if (m_subtarget)
+ m_subtarget->UnregisterObject(m_armature);
+}
+
+BL_ArmatureConstraint* BL_ArmatureConstraint::GetReplica() const
+{
+ BL_ArmatureConstraint* replica = new BL_ArmatureConstraint(*this);
+ replica->ProcessReplica();
+ return replica;
+}
+
+void BL_ArmatureConstraint::ReParent(BL_ArmatureObject* armature)
+{
+ m_armature = armature;
+ if (m_target)
+ m_target->RegisterObject(armature);
+ if (m_subtarget)
+ m_subtarget->RegisterObject(armature);
+ // find the corresponding constraint in the new armature object
+ if (m_constraint) {
+ bPose* newpose = armature->GetOrigPose();
+ char* constraint = m_constraint->name;
+ char* posechannel = m_posechannel->name;
+ bPoseChannel* pchan;
+ bConstraint* pcon;
+ m_constraint = NULL;
+ m_posechannel = NULL;
+ // and locate the constraint
+ for (pchan = (bPoseChannel*)newpose->chanbase.first; pchan; pchan=(bPoseChannel*)pchan->next) {
+ if (!strcmp(pchan->name, posechannel)) {
+ // now locate the constraint
+ for (pcon = (bConstraint*)pchan->constraints.first; pcon; pcon=(bConstraint*)pcon->next) {
+ if (!strcmp(pcon->name, constraint)) {
+ m_constraint = pcon;
+ m_posechannel = pchan;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+void BL_ArmatureConstraint::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
+{
+ void **h_obj = (*obj_map)[m_target];
+ if (h_obj) {
+ m_target->UnregisterObject(m_armature);
+ m_target = (KX_GameObject*)(*h_obj);
+ m_target->RegisterObject(m_armature);
+ }
+ h_obj = (*obj_map)[m_subtarget];
+ if (h_obj) {
+ m_subtarget->UnregisterObject(m_armature);
+ m_subtarget = (KX_GameObject*)(*h_obj);
+ m_subtarget->RegisterObject(m_armature);
+ }
+}
+
+bool BL_ArmatureConstraint::UnlinkObject(SCA_IObject* clientobj)
+{
+ bool res=false;
+ if (clientobj == m_target) {
+ m_target = NULL;
+ res = true;
+ }
+ if (clientobj == m_subtarget) {
+ m_subtarget = NULL;
+ res = true;
+ }
+ return res;
+}
+
+void BL_ArmatureConstraint::UpdateTarget()
+{
+ if (m_constraint && !(m_constraint->flag&CONSTRAINT_OFF) && (!m_blendtarget || m_target)) {
+ if (m_blendtarget) {
+ // external target, must be updated
+ m_target->UpdateBlenderObjectMatrix(m_blendtarget);
+ if (m_pose && m_target->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
+ // update the pose in case a bone is specified in the constraint target
+ m_blendtarget->pose = ((BL_ArmatureObject*)m_target)->GetOrigPose();
+ }
+ if (m_blendsubtarget && m_subtarget) {
+ m_subtarget->UpdateBlenderObjectMatrix(m_blendsubtarget);
+ if (m_subpose && m_subtarget->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
+ m_blendsubtarget->pose = ((BL_ArmatureObject*)m_target)->GetOrigPose();
+ }
+ }
+}
+
+void BL_ArmatureConstraint::RestoreTarget()
+{
+ if (m_constraint && !(m_constraint->flag&CONSTRAINT_OFF) && (!m_blendtarget || m_target)) {
+ if (m_blendtarget) {
+ Mat4CpyMat4(m_blendtarget->obmat, m_blendmat);
+ if (m_pose)
+ m_blendtarget->pose = m_pose;
+ }
+ if (m_blendsubtarget && m_subtarget) {
+ Mat4CpyMat4(m_blendsubtarget->obmat, m_blendsubmat);
+ if (m_subpose)
+ m_blendsubtarget->pose = m_subpose;
+ }
+ }
+}
+
+bool BL_ArmatureConstraint::Match(const char* posechannel, const char* constraint)
+{
+ return (!strcmp(m_posechannel->name, posechannel) && !strcmp(m_constraint->name, constraint));
+}
+
+void BL_ArmatureConstraint::SetTarget(KX_GameObject* target)
+{
+ if (m_blendtarget) {
+ if (target != m_target) {
+ m_target->UnregisterObject(m_armature);
+ m_target = target;
+ if (m_target)
+ m_target->RegisterObject(m_armature);
+ }
+ }
+
+}
+
+void BL_ArmatureConstraint::SetSubtarget(KX_GameObject* subtarget)
+{
+ if (m_blendsubtarget) {
+ if (subtarget != m_subtarget) {
+ m_subtarget->UnregisterObject(m_armature);
+ m_subtarget = subtarget;
+ if (m_subtarget)
+ m_subtarget->RegisterObject(m_armature);
+ }
+ }
+
+}
+
+#ifndef DISABLE_PYTHON
+
+// PYTHON
+
+PyMethodDef BL_ArmatureConstraint::Methods[] = {
+ {NULL,NULL} //Sentinel
+};
+
+// order of definition of attributes, must match Attributes[] array
+#define BCA_TYPE 0
+#define BCA_NAME 1
+#define BCA_ENFORCE 2
+#define BCA_HEADTAIL 3
+#define BCA_LINERROR 4
+#define BCA_ROTERROR 5
+#define BCA_TARGET 6
+#define BCA_SUBTARGET 7
+#define BCA_ACTIVE 8
+#define BCA_IKWEIGHT 9
+#define BCA_IKTYPE 10
+#define BCA_IKFLAG 11
+#define BCA_IKDIST 12
+#define BCA_IKMODE 13
+
+PyAttributeDef BL_ArmatureConstraint::Attributes[] = {
+ // Keep these attributes in order of BCA_ defines!!! used by py_attr_getattr and py_attr_setattr
+ KX_PYATTRIBUTE_RO_FUNCTION("type",BL_ArmatureConstraint,py_attr_getattr),
+ KX_PYATTRIBUTE_RO_FUNCTION("name",BL_ArmatureConstraint,py_attr_getattr),
+ KX_PYATTRIBUTE_RW_FUNCTION("enforce",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
+ KX_PYATTRIBUTE_RW_FUNCTION("headtail",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
+ KX_PYATTRIBUTE_RO_FUNCTION("lin_error",BL_ArmatureConstraint,py_attr_getattr),
+ KX_PYATTRIBUTE_RO_FUNCTION("rot_error",BL_ArmatureConstraint,py_attr_getattr),
+ KX_PYATTRIBUTE_RW_FUNCTION("target",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
+ KX_PYATTRIBUTE_RW_FUNCTION("subtarget",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
+ KX_PYATTRIBUTE_RW_FUNCTION("active",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
+ KX_PYATTRIBUTE_RW_FUNCTION("ik_weight",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
+ KX_PYATTRIBUTE_RO_FUNCTION("ik_type",BL_ArmatureConstraint,py_attr_getattr),
+ KX_PYATTRIBUTE_RO_FUNCTION("ik_flag",BL_ArmatureConstraint,py_attr_getattr),
+ KX_PYATTRIBUTE_RW_FUNCTION("ik_dist",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
+ KX_PYATTRIBUTE_RW_FUNCTION("ik_mode",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
+
+ { NULL } //Sentinel
+};
+
+
+PyObject* BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
+{
+ BL_ArmatureConstraint* self= static_cast<BL_ArmatureConstraint*>(self_v);
+ bConstraint* constraint = self->m_constraint;
+ bKinematicConstraint* ikconstraint = (constraint && constraint->type == CONSTRAINT_TYPE_KINEMATIC) ? (bKinematicConstraint*)constraint->data : NULL;
+ int attr_order = attrdef-Attributes;
+
+ if (!constraint) {
+ PyErr_SetString(PyExc_AttributeError, "constraint is NULL");
+ return NULL;
+ }
+
+ switch (attr_order) {
+ case BCA_TYPE:
+ return PyLong_FromLong(constraint->type);
+ case BCA_NAME:
+ return PyUnicode_FromString(constraint->name);
+ case BCA_ENFORCE:
+ return PyFloat_FromDouble(constraint->enforce);
+ case BCA_HEADTAIL:
+ return PyFloat_FromDouble(constraint->headtail);
+ case BCA_LINERROR:
+ return PyFloat_FromDouble(constraint->lin_error);
+ case BCA_ROTERROR:
+ return PyFloat_FromDouble(constraint->rot_error);
+ case BCA_TARGET:
+ if (!self->m_target)
+ Py_RETURN_NONE;
+ else
+ return self->m_target->GetProxy();
+ case BCA_SUBTARGET:
+ if (!self->m_subtarget)
+ Py_RETURN_NONE;
+ else
+ return self->m_subtarget->GetProxy();
+ case BCA_ACTIVE:
+ return PyBool_FromLong(constraint->flag & CONSTRAINT_OFF);
+ case BCA_IKWEIGHT:
+ case BCA_IKTYPE:
+ case BCA_IKFLAG:
+ case BCA_IKDIST:
+ case BCA_IKMODE:
+ if (!ikconstraint) {
+ PyErr_SetString(PyExc_AttributeError, "constraint is not of IK type");
+ return NULL;
+ }
+ switch (attr_order) {
+ case BCA_IKWEIGHT:
+ return PyFloat_FromDouble((ikconstraint)?ikconstraint->weight:0.0);
+ case BCA_IKTYPE:
+ return PyLong_FromLong(ikconstraint->type);
+ case BCA_IKFLAG:
+ return PyLong_FromLong(ikconstraint->flag);
+ case BCA_IKDIST:
+ return PyFloat_FromDouble(ikconstraint->dist);
+ case BCA_IKMODE:
+ return PyLong_FromLong(ikconstraint->mode);
+ }
+ // should not come here
+ break;
+ }
+ PyErr_SetString(PyExc_AttributeError, "constraint unknown attribute");
+ return NULL;
+}
+
+int BL_ArmatureConstraint::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ BL_ArmatureConstraint* self= static_cast<BL_ArmatureConstraint*>(self_v);
+ bConstraint* constraint = self->m_constraint;
+ bKinematicConstraint* ikconstraint = (constraint && constraint->type == CONSTRAINT_TYPE_KINEMATIC) ? (bKinematicConstraint*)constraint->data : NULL;
+ int attr_order = attrdef-Attributes;
+ int ival;
+ double dval;
+ char* sval;
+ KX_GameObject *oval;
+
+ if (!constraint) {
+ PyErr_SetString(PyExc_AttributeError, "constraint is NULL");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ switch (attr_order) {
+ case BCA_ENFORCE:
+ dval = PyFloat_AsDouble(value);
+ if (dval < 0.0f || dval > 1.0f) { /* also accounts for non float */
+ PyErr_SetString(PyExc_AttributeError, "constraint.enforce = float: BL_ArmatureConstraint, expected a float between 0 and 1");
+ return PY_SET_ATTR_FAIL;
+ }
+ constraint->enforce = dval;
+ return PY_SET_ATTR_SUCCESS;
+
+ case BCA_HEADTAIL:
+ dval = PyFloat_AsDouble(value);
+ if (dval < 0.0f || dval > 1.0f) { /* also accounts for non float */
+ PyErr_SetString(PyExc_AttributeError, "constraint.headtail = float: BL_ArmatureConstraint, expected a float between 0 and 1");
+ return PY_SET_ATTR_FAIL;
+ }
+ constraint->headtail = dval;
+ return PY_SET_ATTR_SUCCESS;
+
+ case BCA_TARGET:
+ if (!ConvertPythonToGameObject(value, &oval, true, "constraint.target = value: BL_ArmatureConstraint"))
+ return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
+ self->SetTarget(oval);
+ return PY_SET_ATTR_SUCCESS;
+
+ case BCA_SUBTARGET:
+ if (!ConvertPythonToGameObject(value, &oval, true, "constraint.subtarget = value: BL_ArmatureConstraint"))
+ return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
+ self->SetSubtarget(oval);
+ return PY_SET_ATTR_SUCCESS;
+
+ case BCA_ACTIVE:
+ ival = PyObject_IsTrue( value );
+ if (ival == -1) {
+ PyErr_SetString(PyExc_AttributeError, "constraint.active = bool: BL_ArmatureConstraint, expected True or False");
+ return PY_SET_ATTR_FAIL;
+ }
+ self->m_constraint->flag = (self->m_constraint->flag & ~CONSTRAINT_OFF) | ((ival)?0:CONSTRAINT_OFF);
+ return PY_SET_ATTR_SUCCESS;
+
+ case BCA_IKWEIGHT:
+ case BCA_IKDIST:
+ case BCA_IKMODE:
+ if (!ikconstraint) {
+ PyErr_SetString(PyExc_AttributeError, "constraint is not of IK type");
+ return PY_SET_ATTR_FAIL;
+ }
+ switch (attr_order) {
+ case BCA_IKWEIGHT:
+ dval = PyFloat_AsDouble(value);
+ if (dval < 0.0f || dval > 1.0f) { /* also accounts for non float */
+ PyErr_SetString(PyExc_AttributeError, "constraint.weight = float: BL_ArmatureConstraint, expected a float between 0 and 1");
+ return PY_SET_ATTR_FAIL;
+ }
+ ikconstraint->weight = dval;
+ return PY_SET_ATTR_SUCCESS;
+
+ case BCA_IKDIST:
+ dval = PyFloat_AsDouble(value);
+ if (dval < 0.0f) { /* also accounts for non float */
+ PyErr_SetString(PyExc_AttributeError, "constraint.ik_dist = float: BL_ArmatureConstraint, expected a positive float");
+ return PY_SET_ATTR_FAIL;
+ }
+ ikconstraint->dist = dval;
+ return PY_SET_ATTR_SUCCESS;
+
+ case BCA_IKMODE:
+ ival = PyLong_AsLong(value);
+ if (ival < 0) {
+ PyErr_SetString(PyExc_AttributeError, "constraint.ik_mode = integer: BL_ArmatureConstraint, expected a positive integer");
+ return PY_SET_ATTR_FAIL;
+ }
+ ikconstraint->mode = ival;
+ return PY_SET_ATTR_SUCCESS;
+ }
+ // should not come here
+ break;
+
+ }
+
+ PyErr_SetString(PyExc_AttributeError, "constraint unknown attribute");
+ return PY_SET_ATTR_FAIL;
+}
+
+#endif // DISABLE_PYTHON
diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.h b/source/gameengine/Converter/BL_ArmatureConstraint.h
new file mode 100644
index 00000000000..2a202dfe62e
--- /dev/null
+++ b/source/gameengine/Converter/BL_ArmatureConstraint.h
@@ -0,0 +1,118 @@
+/**
+ * $Id$
+ *
+ * ***** 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BL_ARMATURECONSTRAINT
+#define __BL_ARMATURECONSTRAINT
+
+#include "DNA_constraint_types.h"
+#include "GEN_HashedPtr.h"
+#include "GEN_Map.h"
+#include "PyObjectPlus.h"
+
+class SCA_IObject;
+class KX_GameObject;
+class BL_ArmatureObject;
+struct bConstraint;
+struct bPoseChannel;
+struct Object;
+struct bPose;
+
+/**
+ * SG_DList : element of controlled constraint list
+ * head = BL_ArmatureObject::m_controlledConstraints
+ * SG_QList : not used
+ */
+class BL_ArmatureConstraint : public PyObjectPlus
+{
+ Py_Header;
+
+private:
+ struct bConstraint* m_constraint;
+ struct bPoseChannel* m_posechannel;
+ class BL_ArmatureObject* m_armature;
+ char m_name[64];
+ KX_GameObject* m_target;
+ KX_GameObject* m_subtarget;
+ struct Object* m_blendtarget;
+ struct Object* m_blendsubtarget;
+ float m_blendmat[4][4];
+ float m_blendsubmat[4][4];
+ struct bPose* m_pose;
+ struct bPose* m_subpose;
+
+public:
+ BL_ArmatureConstraint(class BL_ArmatureObject *armature,
+ struct bPoseChannel *posechannel,
+ struct bConstraint *constraint,
+ KX_GameObject* target,
+ KX_GameObject* subtarget);
+ virtual ~BL_ArmatureConstraint();
+
+ BL_ArmatureConstraint* GetReplica() const;
+ void ReParent(BL_ArmatureObject* armature);
+ void Relink(GEN_Map<GEN_HashedPtr, void*> *map);
+ bool UnlinkObject(SCA_IObject* clientobj);
+
+ void UpdateTarget();
+ void RestoreTarget();
+
+ bool Match(const char* posechannel, const char* constraint);
+ const char* GetName() { return m_name; }
+
+ void SetConstraintFlag(int flag)
+ {
+ if (m_constraint)
+ m_constraint->flag |= flag;
+ }
+ void ClrConstraintFlag(int flag)
+ {
+ if (m_constraint)
+ m_constraint->flag &= ~flag;
+ }
+ void SetWeight(float weight)
+ {
+ if (m_constraint && m_constraint->type == CONSTRAINT_TYPE_KINEMATIC && m_constraint->data) {
+ bKinematicConstraint* con = (bKinematicConstraint*)m_constraint->data;
+ con->weight = weight;
+ }
+ }
+ void SetTarget(KX_GameObject* target);
+ void SetSubtarget(KX_GameObject* subtarget);
+
+#ifndef DISABLE_PYTHON
+
+ // Python access
+ virtual PyObject* py_repr(void);
+
+ static PyObject* py_attr_getattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static int py_attr_setattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+#endif // DISABLE_PYTHON
+};
+
+#endif //__BL_ARMATURECONSTRAINT
+
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index cfd90813a16..a6066adc03e 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -29,9 +29,15 @@
#include "BL_ArmatureObject.h"
#include "BL_ActionActuator.h"
+#include "KX_BlenderSceneConverter.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_arithb.h"
+#include "BIK_api.h"
#include "BKE_action.h"
#include "BKE_armature.h"
+#include "BKE_utildefines.h"
+#include "BKE_constraint.h"
#include "GEN_Map.h"
#include "GEN_HashedPtr.h"
#include "MEM_guardedalloc.h"
@@ -39,6 +45,11 @@
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_constraint_types.h"
+#include "KX_PythonSeq.h"
+#include "KX_PythonInit.h"
+#include "KX_KetsjiEngine.h"
#include "MT_Matrix4x4.h"
@@ -46,6 +57,153 @@
#include <config.h>
#endif
+/**
+ * Move here pose function for game engine so that we can mix with GE objects
+ * Principle is as follow:
+ * Use Blender structures so that where_is_pose can be used unchanged
+ * Copy the constraint so that they can be enabled/disabled/added/removed at runtime
+ * Don't copy the constraints for the pose used by the Action actuator, it does not need them.
+ * Scan the constraint structures so that the KX equivalent of target objects are identified and
+ * stored in separate list.
+ * When it is about to evaluate the pose, set the KX object position in the obmat of the corresponding
+ * Blender objects and restore after the evaluation.
+ */
+void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
+{
+ bPose *out;
+ bPoseChannel *pchan, *outpchan;
+ GHash *ghash;
+
+ /* the game engine copies the current armature pose and then swaps
+ * the object pose pointer. this makes it possible to change poses
+ * without affecting the original blender data. */
+
+ if (!src) {
+ *dst=NULL;
+ return;
+ }
+ else if (*dst==src) {
+ printf("copy_pose source and target are the same\n");
+ *dst=NULL;
+ return;
+ }
+
+ out= (bPose*)MEM_dupallocN(src);
+ out->agroups.first= out->agroups.last= NULL;
+ out->ikdata = NULL;
+ out->ikparam = MEM_dupallocN(out->ikparam);
+ out->flag |= POSE_GAME_ENGINE;
+ BLI_duplicatelist(&out->chanbase, &src->chanbase);
+
+ /* remap pointers */
+ ghash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ pchan= (bPoseChannel*)src->chanbase.first;
+ outpchan= (bPoseChannel*)out->chanbase.first;
+ for (; pchan; pchan=pchan->next, outpchan=outpchan->next)
+ BLI_ghash_insert(ghash, pchan, outpchan);
+
+ for (pchan=(bPoseChannel*)out->chanbase.first; pchan; pchan=(bPoseChannel*)pchan->next) {
+ pchan->parent= (bPoseChannel*)BLI_ghash_lookup(ghash, pchan->parent);
+ pchan->child= (bPoseChannel*)BLI_ghash_lookup(ghash, pchan->child);
+ pchan->path= NULL;
+
+ if (copy_constraint) {
+ ListBase listb;
+ // copy all constraint for backward compatibility
+ copy_constraints(&listb, &pchan->constraints); // copy_constraints NULLs listb
+ pchan->constraints= listb;
+ } else {
+ pchan->constraints.first = NULL;
+ pchan->constraints.last = NULL;
+ }
+ }
+
+ BLI_ghash_free(ghash, NULL, NULL);
+
+ *dst=out;
+}
+
+
+
+/* Only allowed for Poses with identical channels */
+void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/)
+{
+ short mode= ACTSTRIPMODE_BLEND;
+
+ bPoseChannel *dchan;
+ const bPoseChannel *schan;
+ bConstraint *dcon, *scon;
+ float dstweight;
+ int i;
+
+ switch (mode){
+ case ACTSTRIPMODE_BLEND:
+ dstweight = 1.0F - srcweight;
+ break;
+ case ACTSTRIPMODE_ADD:
+ dstweight = 1.0F;
+ break;
+ default :
+ dstweight = 1.0F;
+ }
+
+ schan= (bPoseChannel*)src->chanbase.first;
+ for (dchan = (bPoseChannel*)dst->chanbase.first; dchan; dchan=(bPoseChannel*)dchan->next, schan= (bPoseChannel*)schan->next){
+ // always blend on all channels since we don't know which one has been set
+ /* quat interpolation done separate */
+ if (schan->rotmode == ROT_MODE_QUAT) {
+ float dquat[4], squat[4];
+
+ QUATCOPY(dquat, dchan->quat);
+ QUATCOPY(squat, schan->quat);
+ if (mode==ACTSTRIPMODE_BLEND)
+ QuatInterpol(dchan->quat, dquat, squat, srcweight);
+ else {
+ QuatMulFac(squat, srcweight);
+ QuatMul(dchan->quat, dquat, squat);
+ }
+
+ NormalQuat(dchan->quat);
+ }
+
+ for (i=0; i<3; i++) {
+ /* blending for loc and scale are pretty self-explanatory... */
+ dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight);
+ dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight);
+
+ /* euler-rotation interpolation done here instead... */
+ // FIXME: are these results decent?
+ if (schan->rotmode)
+ dchan->eul[i] = (dchan->eul[i]*dstweight) + (schan->eul[i]*srcweight);
+ }
+ for(dcon= (bConstraint*)dchan->constraints.first, scon= (bConstraint*)schan->constraints.first; dcon && scon; dcon= (bConstraint*)dcon->next, scon= (bConstraint*)scon->next) {
+ /* no 'add' option for constraint blending */
+ dcon->enforce= dcon->enforce*(1.0f-srcweight) + scon->enforce*srcweight;
+ }
+ }
+
+ /* this pose is now in src time */
+ dst->ctime= src->ctime;
+}
+
+void game_free_pose(bPose *pose)
+{
+ if (pose) {
+ /* free pose-channels and constraints */
+ free_pose_channels(pose);
+
+ /* free IK solver state */
+ BIK_clear_data(pose);
+
+ /* free IK solver param */
+ if (pose->ikparam)
+ MEM_freeN(pose->ikparam);
+
+ MEM_freeN(pose);
+ }
+}
+
BL_ArmatureObject::BL_ArmatureObject(
void* sgReplicationInfo,
SG_Callbacks callbacks,
@@ -53,12 +211,17 @@ BL_ArmatureObject::BL_ArmatureObject(
Scene *scene)
: KX_GameObject(sgReplicationInfo,callbacks),
+ m_controlledConstraints(),
+ m_poseChannels(),
m_objArma(armature),
m_framePose(NULL),
m_scene(scene), // maybe remove later. needed for where_is_pose
m_lastframe(0.0),
+ m_timestep(0.040),
m_activeAct(NULL),
m_activePriority(999),
+ m_constraintNumber(0),
+ m_channelNumber(0),
m_lastapplyframe(0.0)
{
m_armature = (bArmature *)armature->data;
@@ -67,7 +230,177 @@ BL_ArmatureObject::BL_ArmatureObject(
* 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);
+ game_copy_pose(&m_pose, m_objArma->pose, 1);
+ // store the original armature object matrix
+ memcpy(m_obmat, m_objArma->obmat, sizeof(m_obmat));
+}
+
+BL_ArmatureObject::~BL_ArmatureObject()
+{
+ BL_ArmatureConstraint* constraint;
+ while ((constraint = m_controlledConstraints.Remove()) != NULL) {
+ delete constraint;
+ }
+ BL_ArmatureChannel* channel;
+ while ((channel = static_cast<BL_ArmatureChannel*>(m_poseChannels.Remove())) != NULL) {
+ delete channel;
+ }
+ if (m_pose)
+ game_free_pose(m_pose);
+ if (m_framePose)
+ game_free_pose(m_framePose);
+}
+
+
+void BL_ArmatureObject::LoadConstraints(KX_BlenderSceneConverter* converter)
+{
+ // first delete any existing constraint (should not have any)
+ while (!m_controlledConstraints.Empty()) {
+ BL_ArmatureConstraint* constraint = m_controlledConstraints.Remove();
+ delete constraint;
+ }
+ m_constraintNumber = 0;
+
+ // list all the constraint and convert them to BL_ArmatureConstraint
+ // get the persistent pose structure
+ bPoseChannel* pchan;
+ bConstraint* pcon;
+ bConstraintTypeInfo* cti;
+ Object* blendtarget;
+ KX_GameObject* gametarget;
+ KX_GameObject* gamesubtarget;
+
+ // and locate the constraint
+ for (pchan = (bPoseChannel*)m_pose->chanbase.first; pchan; pchan=(bPoseChannel*)pchan->next) {
+ for (pcon = (bConstraint*)pchan->constraints.first; pcon; pcon=(bConstraint*)pcon->next) {
+ if (pcon->flag & CONSTRAINT_DISABLE)
+ continue;
+ // which constraint should we support?
+ switch (pcon->type) {
+ case CONSTRAINT_TYPE_TRACKTO:
+ case CONSTRAINT_TYPE_KINEMATIC:
+ case CONSTRAINT_TYPE_ROTLIKE:
+ case CONSTRAINT_TYPE_LOCLIKE:
+ case CONSTRAINT_TYPE_MINMAX:
+ case CONSTRAINT_TYPE_SIZELIKE:
+ case CONSTRAINT_TYPE_LOCKTRACK:
+ case CONSTRAINT_TYPE_STRETCHTO:
+ case CONSTRAINT_TYPE_CLAMPTO:
+ case CONSTRAINT_TYPE_TRANSFORM:
+ case CONSTRAINT_TYPE_DISTLIMIT:
+ cti = constraint_get_typeinfo(pcon);
+ gametarget = gamesubtarget = NULL;
+ if (cti && cti->get_constraint_targets) {
+ ListBase listb = { NULL, NULL };
+ cti->get_constraint_targets(pcon, &listb);
+ if (listb.first) {
+ bConstraintTarget* target = (bConstraintTarget*)listb.first;
+ if (target->tar && target->tar != m_objArma) {
+ // only remember external objects, self target is handled automatically
+ blendtarget = target->tar;
+ gametarget = converter->FindGameObject(blendtarget);
+ }
+ if (target->next != NULL) {
+ // secondary target
+ target = (bConstraintTarget*)target->next;
+ if (target->tar && target->tar != m_objArma) {
+ // only track external object
+ blendtarget = target->tar;
+ gamesubtarget = converter->FindGameObject(blendtarget);
+ }
+ }
+ }
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(pcon, &listb, 1);
+ }
+ BL_ArmatureConstraint* constraint = new BL_ArmatureConstraint(this, pchan, pcon, gametarget, gamesubtarget);
+ m_controlledConstraints.AddBack(constraint);
+ m_constraintNumber++;
+ }
+ }
+ }
+}
+
+BL_ArmatureConstraint* BL_ArmatureObject::GetConstraint(const char* posechannel, const char* constraintname)
+{
+ SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints);
+ for (cit.begin(); !cit.end(); ++cit) {
+ BL_ArmatureConstraint* constraint = *cit;
+ if (constraint->Match(posechannel, constraintname))
+ return constraint;
+ }
+ return NULL;
+}
+
+BL_ArmatureConstraint* BL_ArmatureObject::GetConstraint(const char* posechannelconstraint)
+{
+ // performance: use hash string instead of plain string compare
+ SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints);
+ for (cit.begin(); !cit.end(); ++cit) {
+ BL_ArmatureConstraint* constraint = *cit;
+ if (!strcmp(constraint->GetName(), posechannelconstraint))
+ return constraint;
+ }
+ return NULL;
+}
+
+BL_ArmatureConstraint* BL_ArmatureObject::GetConstraint(int index)
+{
+ SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints);
+ for (cit.begin(); !cit.end() && index; ++cit, --index);
+ return (cit.end()) ? NULL : *cit;
+}
+
+/* this function is called to populate the m_poseChannels list */
+void BL_ArmatureObject::LoadChannels()
+{
+ if (m_poseChannels.Empty()) {
+ bPoseChannel* pchan;
+ BL_ArmatureChannel* proxy;
+
+ m_channelNumber = 0;
+ for (pchan = (bPoseChannel*)m_pose->chanbase.first; pchan; pchan=(bPoseChannel*)pchan->next) {
+ proxy = new BL_ArmatureChannel(this, pchan);
+ m_poseChannels.AddBack(proxy);
+ m_channelNumber++;
+ }
+ }
+}
+
+BL_ArmatureChannel* BL_ArmatureObject::GetChannel(bPoseChannel* pchan)
+{
+ LoadChannels();
+ SG_DList::iterator<BL_ArmatureChannel> cit(m_poseChannels);
+ for (cit.begin(); !cit.end(); ++cit)
+ {
+ BL_ArmatureChannel* channel = *cit;
+ if (channel->m_posechannel == pchan)
+ return channel;
+ }
+ return NULL;
+}
+
+BL_ArmatureChannel* BL_ArmatureObject::GetChannel(const char* str)
+{
+ LoadChannels();
+ SG_DList::iterator<BL_ArmatureChannel> cit(m_poseChannels);
+ for (cit.begin(); !cit.end(); ++cit)
+ {
+ BL_ArmatureChannel* channel = *cit;
+ if (!strcmp(channel->m_posechannel->name, str))
+ return channel;
+ }
+ return NULL;
+}
+
+BL_ArmatureChannel* BL_ArmatureObject::GetChannel(int index)
+{
+ LoadChannels();
+ if (index < 0 || index >= m_channelNumber)
+ return NULL;
+ SG_DList::iterator<BL_ArmatureChannel> cit(m_poseChannels);
+ for (cit.begin(); !cit.end() && index; ++cit, --index);
+ return (cit.end()) ? NULL : *cit;
}
CValue* BL_ArmatureObject::GetReplica()
@@ -83,22 +416,61 @@ void BL_ArmatureObject::ProcessReplica()
KX_GameObject::ProcessReplica();
m_pose = NULL;
- game_copy_pose(&m_pose, pose);
+ m_framePose = NULL;
+ game_copy_pose(&m_pose, pose, 1);
}
-BL_ArmatureObject::~BL_ArmatureObject()
+void BL_ArmatureObject::ReParentLogic()
{
- if (m_pose)
- game_free_pose(m_pose);
+ SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints);
+ for (cit.begin(); !cit.end(); ++cit) {
+ (*cit)->ReParent(this);
+ }
+ KX_GameObject::ReParentLogic();
+}
+
+void BL_ArmatureObject::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
+{
+ SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints);
+ for (cit.begin(); !cit.end(); ++cit) {
+ (*cit)->Relink(obj_map);
+ }
+ KX_GameObject::Relink(obj_map);
+}
+
+bool BL_ArmatureObject::UnlinkObject(SCA_IObject* clientobj)
+{
+ // clientobj is being deleted, make sure we don't hold any reference to it
+ bool res = false;
+ SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints);
+ for (cit.begin(); !cit.end(); ++cit) {
+ res |= (*cit)->UnlinkObject(clientobj);
+ }
+ return res;
}
void BL_ArmatureObject::ApplyPose()
{
m_armpose = m_objArma->pose;
m_objArma->pose = m_pose;
+ // in the GE, we use ctime to store the timestep
+ m_pose->ctime = (float)m_timestep;
//m_scene->r.cfra++;
if(m_lastapplyframe != m_lastframe) {
+ // update the constraint if any, first put them all off so that only the active ones will be updated
+ SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints);
+ for (cit.begin(); !cit.end(); ++cit) {
+ (*cit)->UpdateTarget();
+ }
+ // update ourself
+ UpdateBlenderObjectMatrix(m_objArma);
where_is_pose(m_scene, m_objArma); // XXX
+ // restore ourself
+ memcpy(m_objArma->obmat, m_obmat, sizeof(m_obmat));
+ // restore active targets
+ for (cit.begin(); !cit.end(); ++cit) {
+ (*cit)->RestoreTarget();
+ }
m_lastapplyframe = m_lastframe;
}
}
@@ -119,30 +491,37 @@ bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority,
{
if (curtime != m_lastframe){
m_activePriority = 9999;
+ // compute the timestep for the underlying IK algorithm
+ m_timestep = curtime-m_lastframe;
m_lastframe= curtime;
m_activeAct = NULL;
// remember the pose at the start of the frame
- m_framePose = m_pose;
+ GetPose(&m_framePose);
}
- if (priority<=m_activePriority)
+ if (act)
{
- 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;
- m_activePriority = priority;
- m_lastframe = curtime;
-
- return true;
- }
- else{
- act->SetBlendTime(0.0);
- return false;
+ if (priority<=m_activePriority)
+ {
+ if (priority<m_activePriority) {
+ // this action overwrites the previous ones, start from initial pose to cancel their effects
+ SetPose(m_framePose);
+ if (m_activeAct && (m_activeAct!=act))
+ /* Reset the blend timer since this new action cancels the old one */
+ m_activeAct->SetBlendTime(0.0);
+ }
+ m_activeAct = act;
+ m_activePriority = priority;
+ m_lastframe = curtime;
+
+ return true;
+ }
+ else{
+ act->SetBlendTime(0.0);
+ return false;
+ }
}
-
+ return false;
}
BL_ActionActuator * BL_ArmatureObject::GetActiveAction()
@@ -161,7 +540,7 @@ void BL_ArmatureObject::GetPose(bPose **pose)
a crash and memory leakage when
&BL_ActionActuator::m_pose is freed
*/
- game_copy_pose(pose, m_pose);
+ game_copy_pose(pose, m_pose, 0);
}
else {
if (*pose == m_pose)
@@ -178,7 +557,7 @@ void BL_ArmatureObject::GetMRDPose(bPose **pose)
/* Otherwise, copy the armature's pose channels into the caller-supplied pose */
if (!*pose)
- game_copy_pose(pose, m_pose);
+ game_copy_pose(pose, m_pose, 0);
else
extract_pose_from_pose(*pose, m_pose);
}
@@ -210,3 +589,72 @@ float BL_ArmatureObject::GetBoneLength(Bone* bone) const
{
return (float)(MT_Point3(bone->head) - MT_Point3(bone->tail)).length();
}
+
+#ifndef DISABLE_PYTHON
+
+// PYTHON
+
+PyTypeObject BL_ArmatureObject::Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BL_ArmatureObject",
+ sizeof(PyObjectPlus_Proxy),
+ 0,
+ py_base_dealloc,
+ 0,
+ 0,
+ 0,
+ 0,
+ py_base_repr,
+ 0,
+ &KX_GameObject::Sequence,
+ &KX_GameObject::Mapping,
+ 0,0,0,
+ NULL,
+ NULL,
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ 0,0,0,0,0,0,0,
+ Methods,
+ 0,
+ 0,
+ &KX_GameObject::Type,
+ 0,0,0,0,0,0,
+ py_base_new
+};
+
+PyMethodDef BL_ArmatureObject::Methods[] = {
+
+ KX_PYMETHODTABLE_NOARGS(BL_ArmatureObject, update),
+ {NULL,NULL} //Sentinel
+};
+
+PyAttributeDef BL_ArmatureObject::Attributes[] = {
+
+ KX_PYATTRIBUTE_RO_FUNCTION("constraints", BL_ArmatureObject, pyattr_get_constraints),
+ KX_PYATTRIBUTE_RO_FUNCTION("channels", BL_ArmatureObject, pyattr_get_channels),
+ {NULL} //Sentinel
+};
+
+PyObject* BL_ArmatureObject::pyattr_get_constraints(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ return KX_PythonSeq_CreatePyObject((static_cast<BL_ArmatureObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONSTRAINTS);
+}
+
+PyObject* BL_ArmatureObject::pyattr_get_channels(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ BL_ArmatureObject* self = static_cast<BL_ArmatureObject*>(self_v);
+ self->LoadChannels(); // make sure we have the channels
+ return KX_PythonSeq_CreatePyObject((static_cast<BL_ArmatureObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CHANNELS);
+}
+
+KX_PYMETHODDEF_DOC_NOARGS(BL_ArmatureObject, update,
+ "update()\n"
+ "Make sure that the armature will be updated on next graphic frame.\n"
+ "This is automatically done if a KX_ArmatureActuator with mode run is active\n"
+ "or if an action is playing. This function is usefull in other cases.\n")
+{
+ SetActiveAction(NULL, 0, KX_GetActiveEngine()->GetFrameTime());
+ Py_RETURN_NONE;
+}
+
+#endif // DISABLE_PYTHON
diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h
index af0b7dc201c..b7ef38468bb 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.h
+++ b/source/gameengine/Converter/BL_ArmatureObject.h
@@ -31,21 +31,34 @@
#define BL_ARMATUREOBJECT
#include "KX_GameObject.h"
+#include "BL_ArmatureConstraint.h"
+#include "BL_ArmatureChannel.h"
#include "SG_IObject.h"
+#include <vector>
+#include <algorithm>
struct bArmature;
struct Bone;
+struct bConstraint;
class BL_ActionActuator;
+class BL_ArmatureActuator;
class MT_Matrix4x4;
struct Object;
+class KX_BlenderSceneConverter;
class BL_ArmatureObject : public KX_GameObject
{
+ Py_Header;
public:
+
double GetLastFrame ();
short GetActivePriority();
virtual void ProcessReplica();
+ virtual void ReParentLogic();
+ virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
+ virtual bool UnlinkObject(SCA_IObject* clientobj);
+
class BL_ActionActuator * GetActiveAction();
BL_ArmatureObject(
@@ -73,6 +86,19 @@ public:
Object* GetArmatureObject() {return m_objArma;}
+ // for constraint python API
+ void LoadConstraints(KX_BlenderSceneConverter* converter);
+ size_t GetConstraintNumber() const { return m_constraintNumber; }
+ BL_ArmatureConstraint* GetConstraint(const char* posechannel, const char* constraint);
+ BL_ArmatureConstraint* GetConstraint(const char* posechannelconstraint);
+ BL_ArmatureConstraint* GetConstraint(int index);
+ // for pose channel python API
+ void LoadChannels();
+ size_t GetChannelNumber() const { return m_constraintNumber; }
+ BL_ArmatureChannel* GetChannel(bPoseChannel* channel);
+ BL_ArmatureChannel* GetChannel(const char* channel);
+ BL_ArmatureChannel* GetChannel(int index);
+
/// Retrieve the pose matrix for the specified bone.
/// Returns true on success.
bool GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix);
@@ -81,7 +107,21 @@ public:
float GetBoneLength(Bone* bone) const;
virtual int GetGameObjectType() { return OBJ_ARMATURE; }
+
+#ifndef DISABLE_PYTHON
+
+ // PYTHON
+ static PyObject* pyattr_get_constraints(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_channels(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ KX_PYMETHOD_DOC_NOARGS(BL_ArmatureObject, update);
+
+#endif // DISABLE_PYTHON
+
protected:
+ /* list element: BL_ArmatureConstraint. Use SG_DListHead to have automatic list replication */
+ SG_DListHead<BL_ArmatureConstraint> m_controlledConstraints;
+ /* list element: BL_ArmatureChannel. Use SG_DList to avoid list replication */
+ SG_DList m_poseChannels;
Object *m_objArma;
struct bArmature *m_armature;
struct bPose *m_pose;
@@ -89,18 +129,23 @@ protected:
struct bPose *m_framePose;
struct Scene *m_scene; // need for where_is_pose
double m_lastframe;
+ double m_timestep; // delta since last pose evaluation.
class BL_ActionActuator *m_activeAct;
short m_activePriority;
+ size_t m_constraintNumber;
+ size_t m_channelNumber;
+ // store the original armature object matrix
+ float m_obmat[4][4];
double m_lastapplyframe;
+};
+/* Pose function specific to the game engine */
+void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight/*, short mode*/); /* was blend_poses */
+//void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
+void game_copy_pose(struct bPose **dst, struct bPose *src, int copy_con);
+void game_free_pose(struct bPose *pose);
-#ifdef WITH_CXX_GUARDEDALLOC
-public:
- void *operator new( unsigned int num_bytes) { return MEM_mallocN(num_bytes, "GE:BL_ArmatureObject"); }
- void operator delete( void *mem ) { MEM_freeN(mem); }
-#endif
-};
#endif
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 230820719aa..db32f18f63b 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -838,8 +838,10 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
if (mface->v4)
tan3 = tangent[f*4 + 3];
}
-
- ma = give_current_material(blenderobj, mface->mat_nr+1);
+ if(blenderobj)
+ ma = give_current_material(blenderobj, mface->mat_nr+1);
+ else
+ ma = mesh->mat ? mesh->mat[mface->mat_nr]:NULL;
{
bool visible = true;
@@ -1895,7 +1897,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
KX_Scene* kxscene,
KX_KetsjiEngine* ketsjiEngine,
e_PhysicsEngine physics_engine,
- PyObject* pythondictionary,
RAS_IRenderTools* rendertools,
RAS_ICanvas* canvas,
KX_BlenderSceneConverter* converter,
@@ -2501,6 +2502,14 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
gameobj->GetDeformer()->UpdateBuckets();
}
+ // Set up armature constraints
+ for (i=0;i<sumolist->GetCount();++i)
+ {
+ KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i);
+ if (gameobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
+ ((BL_ArmatureObject*)gameobj)->LoadConstraints(converter);
+ }
+
bool processCompoundChildren = false;
// create physics information
@@ -2643,7 +2652,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
struct Object* blenderobj = gameobj->GetBlenderObject();
int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0;
bool isInActiveLayer = (blenderobj->lay & layerMask)!=0;
- BL_ConvertControllers(blenderobj,gameobj,logicmgr,pythondictionary,layerMask,isInActiveLayer,converter);
+ BL_ConvertControllers(blenderobj,gameobj,logicmgr, layerMask,isInActiveLayer,converter);
}
for ( i=0;i<logicbrick_conversionlist->GetCount();i++)
{
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.h b/source/gameengine/Converter/BL_BlenderDataConversion.h
index b8f9d1ec4e6..218b296b47b 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.h
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.h
@@ -40,7 +40,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
class KX_Scene* kxscene,
class KX_KetsjiEngine* ketsjiEngine,
e_PhysicsEngine physics_engine,
- PyObject* pythondictionary,
class RAS_IRenderTools* rendertools,
class RAS_ICanvas* canvas,
class KX_BlenderSceneConverter* sceneconverter,
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
index 81ce9ff6154..0af6556f285 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
@@ -412,6 +412,8 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame)
return keepgoing;
};
+#ifndef DISABLE_PYTHON
+
/* ------------------------------------------------------------------------- */
/* Python functions */
/* ------------------------------------------------------------------------- */
@@ -492,3 +494,5 @@ int BL_ShapeActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE
return PY_SET_ATTR_SUCCESS;
}
+
+#endif // DISABLE_PYTHON
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h
index 28a6d90abdf..efb1293a5eb 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.h
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.h
@@ -51,7 +51,7 @@ public:
short blendin,
short priority,
float stride)
- : SCA_IActuator(gameobj),
+ : SCA_IActuator(gameobj, KX_ACT_SHAPEACTION),
m_lastpos(0, 0, 0),
m_blendframe(0),
@@ -82,6 +82,8 @@ public:
bAction* GetAction() { return m_action; }
void SetAction(bAction* act) { m_action= act; }
+#ifndef DISABLE_PYTHON
+
static PyObject* pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
@@ -123,6 +125,8 @@ public:
}
+#endif // DISABLE_PYTHON
+
protected:
void SetStartTime(float curtime);
diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt
index 257ca856b2c..f9af2c23629 100644
--- a/source/gameengine/Converter/CMakeLists.txt
+++ b/source/gameengine/Converter/CMakeLists.txt
@@ -59,9 +59,15 @@ SET(INC
../../../source/blender/misc
../../../source/blender/blenloader
../../../source/blender/gpu
+ ../../../source/blender/ikplugin
../../../extern/bullet2/src
- ${PYTHON_INC}
)
+IF(WITH_PYTHON)
+ SET(INC ${INC} ${PYTHON_INC})
+ELSE(WITH_PYTHON)
+ ADD_DEFINITIONS(-DDISABLE_PYTHON)
+ENDIF(WITH_PYTHON)
+
BLENDERLIB(bf_converter "${SRC}" "${INC}")
#env.BlenderLib ( 'bf_converter', sources, Split(incs), [], libtype=['game','player'], priority=[5,70] )
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index 151564391f3..26b4514061c 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -243,7 +243,6 @@ struct BlenderDebugDraw : public btIDebugDraw
#endif
void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
- PyObject* dictobj,
class RAS_IRenderTools* rendertools,
class RAS_ICanvas* canvas)
{
@@ -328,7 +327,6 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
destinationscene,
m_ketsjiEngine,
physics_engine,
- dictobj,
rendertools,
canvas,
this,
@@ -920,3 +918,10 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
}
+
+#ifndef DISABLE_PYTHON
+PyObject *KX_BlenderSceneConverter::GetPyNamespace()
+{
+ return m_ketsjiEngine->GetPyNamespace();
+}
+#endif
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h
index bb87a21a683..f74944d3552 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.h
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h
@@ -89,7 +89,6 @@ public:
*/
virtual void ConvertScene(
class KX_Scene* destinationscene,
- PyObject* dictobj,
class RAS_IRenderTools* rendertools,
class RAS_ICanvas* canvas
);
@@ -143,6 +142,9 @@ public:
struct Main* GetMain() { return m_maggie; };
+#ifndef DISABLE_PYTHON
+ PyObject *GetPyNamespace();
+#endif
#ifdef WITH_CXX_GUARDEDALLOC
public:
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index 91a39bd7686..1cb16acf148 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -88,6 +88,7 @@
#include "DNA_packedFile_types.h"
#include "BL_ActionActuator.h"
#include "BL_ShapeActionActuator.h"
+#include "BL_ArmatureActuator.h"
/* end of blender include block */
#include "BL_BlenderDataConversion.h"
@@ -1021,6 +1022,15 @@ void BL_ConvertActuators(char* maggiename,
break;
}
+ case ACT_ARMATURE:
+ {
+ bArmatureActuator* armAct = (bArmatureActuator*) bact->data;
+ KX_GameObject *tmpgob = converter->FindGameObject(armAct->target);
+ KX_GameObject *subgob = converter->FindGameObject(armAct->subtarget);
+ BL_ArmatureActuator* tmparmact = new BL_ArmatureActuator(gameobj, armAct->type, armAct->posechannel, armAct->constraint, tmpgob, subgob, armAct->weight);
+ baseact = tmparmact;
+ break;
+ }
default:
; /* generate some error */
}
diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp
index 85ab8e4f8b8..faef0feaf48 100644
--- a/source/gameengine/Converter/KX_ConvertControllers.cpp
+++ b/source/gameengine/Converter/KX_ConvertControllers.cpp
@@ -91,8 +91,7 @@ LinkControllerToActuators(
void BL_ConvertControllers(
struct Object* blenderobject,
class KX_GameObject* gameobj,
- SCA_LogicManager* logicmgr,
- PyObject* pythondictionary,
+ SCA_LogicManager* logicmgr,
int activeLayerBitInfo,
bool isInActiveLayer,
KX_BlenderSceneConverter* converter
@@ -158,8 +157,9 @@ void BL_ConvertControllers(
bPythonCont* pycont = (bPythonCont*) bcontr->data;
SCA_PythonController* pyctrl = new SCA_PythonController(gameobj, pycont->mode);
gamecontroller = pyctrl;
-
- pyctrl->SetDictionary(pythondictionary);
+#ifndef DISABLE_PYTHON
+
+ pyctrl->SetNamespace(converter->GetPyNamespace());
if(pycont->mode==SCA_PythonController::SCA_PYEXEC_SCRIPT) {
if (pycont->text)
@@ -187,6 +187,8 @@ void BL_ConvertControllers(
pyctrl->SetDebug(true);
}
+#endif // DISABLE_PYTHON
+
break;
}
default:
@@ -211,7 +213,8 @@ void BL_ConvertControllers(
gameobj->AddController(gamecontroller);
converter->RegisterGameController(gamecontroller, bcontr);
-
+
+#ifndef DISABLE_PYTHON
if (bcontr->type==CONT_PYTHON) {
SCA_PythonController *pyctrl= static_cast<SCA_PythonController*>(gamecontroller);
/* not strictly needed but gives syntax errors early on and
@@ -226,7 +229,8 @@ void BL_ConvertControllers(
// pyctrl->Import();
}
}
-
+#endif // DISABLE_PYTHON
+
//done with gamecontroller
gamecontroller->Release();
}
diff --git a/source/gameengine/Converter/KX_ConvertControllers.h b/source/gameengine/Converter/KX_ConvertControllers.h
index d340778290c..2689ad446bd 100644
--- a/source/gameengine/Converter/KX_ConvertControllers.h
+++ b/source/gameengine/Converter/KX_ConvertControllers.h
@@ -34,8 +34,7 @@
void BL_ConvertControllers(
struct Object* blenderobject,
class KX_GameObject* gameobj,
- class SCA_LogicManager* logicmgr,
- PyObject* pythondictionary,
+ class SCA_LogicManager* logicmgr,
int activeLayerBitInfo,
bool isInActiveLayer,
class KX_BlenderSceneConverter* converter
diff --git a/source/gameengine/Converter/KX_ConvertProperties.cpp b/source/gameengine/Converter/KX_ConvertProperties.cpp
index 1c22d2a0600..7ecdb6c5db6 100644
--- a/source/gameengine/Converter/KX_ConvertProperties.cpp
+++ b/source/gameengine/Converter/KX_ConvertProperties.cpp
@@ -130,7 +130,7 @@ void BL_ConvertProperties(Object* object,KX_GameObject* gameobj,SCA_TimeEventMan
propval->Release();
}
-
+#ifndef DISABLE_PYTHON
/* Warn if we double up on attributes, this isnt quite right since it wont find inherited attributes however there arnt many */
for(PyAttributeDef *attrdef = KX_GameObject::Attributes; attrdef->m_name; attrdef++) {
if(strcmp(prop->name, attrdef->m_name)==0) {
@@ -145,6 +145,7 @@ void BL_ConvertProperties(Object* object,KX_GameObject* gameobj,SCA_TimeEventMan
}
}
/* end warning check */
+#endif // DISABLE_PYTHON
prop = prop->next;
}
diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp
index 09027f18844..692cc91f340 100644
--- a/source/gameengine/Converter/KX_ConvertSensors.cpp
+++ b/source/gameengine/Converter/KX_ConvertSensors.cpp
@@ -28,6 +28,7 @@
* Conversion of Blender data blocks to KX sensor system
*/
+#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -64,6 +65,7 @@ probably misplaced */
#include "KX_NearSensor.h"
#include "KX_RadarSensor.h"
#include "KX_MouseFocusSensor.h"
+#include "KX_ArmatureSensor.h"
#include "SCA_JoystickSensor.h"
#include "KX_NetworkMessageSensor.h"
#include "SCA_ActuatorSensor.h"
@@ -302,7 +304,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
case SENS_ALWAYS:
{
- SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::ALWAYS_EVENTMGR);
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
if (eventmgr)
{
gamesensor = new SCA_AlwaysSensor(eventmgr, gameobj);
@@ -314,7 +316,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
case SENS_DELAY:
{
// we can reuse the Always event manager for the delay sensor
- SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::ALWAYS_EVENTMGR);
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
if (eventmgr)
{
bDelaySensor* delaysensor = (bDelaySensor*)sens->data;
@@ -550,7 +552,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
{
bPropertySensor* blenderpropsensor = (bPropertySensor*) sens->data;
SCA_EventManager* eventmgr
- = logicmgr->FindEventManager(SCA_EventManager::PROPERTY_EVENTMGR);
+ = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
if (eventmgr)
{
STR_String propname=blenderpropsensor->name;
@@ -601,6 +603,21 @@ void BL_ConvertSensors(struct Object* blenderobject,
break;
}
+ case SENS_ARMATURE:
+ {
+ bArmatureSensor* blenderarmsensor = (bArmatureSensor*) sens->data;
+ // we will reuse the property event manager, there is nothing special with this sensor
+ SCA_EventManager* eventmgr
+ = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
+ if (eventmgr)
+ {
+ STR_String bonename=blenderarmsensor->posechannel;
+ STR_String constraintname=blenderarmsensor->constraint;
+ gamesensor = new KX_ArmatureSensor(eventmgr,gameobj,bonename,constraintname, blenderarmsensor->type, blenderarmsensor->value);
+ }
+ break;
+ }
+
case SENS_RADAR:
{
@@ -659,7 +676,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
bRaySensor* blenderraysensor = (bRaySensor*) sens->data;
//blenderradarsensor->angle;
- SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::RAY_EVENTMGR);
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
if (eventmgr)
{
bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL);
@@ -691,7 +708,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
// some files didn't write randomsensor, avoid crash now for NULL ptr's
if (blenderrndsensor)
{
- SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::RANDOM_EVENTMGR);
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
if (eventmgr)
{
int randomSeed = blenderrndsensor->seed;
diff --git a/source/gameengine/Converter/Makefile b/source/gameengine/Converter/Makefile
index e261f9350e9..d41cc705087 100644
--- a/source/gameengine/Converter/Makefile
+++ b/source/gameengine/Converter/Makefile
@@ -53,6 +53,7 @@ CPPFLAGS += -I../../blender/blenlib
CPPFLAGS += -I../../blender/blenkernel
CPPFLAGS += -I../../blender/render/extern/include
CPPFLAGS += -I../../blender/gpu
+CPPFLAGS += -I../../blender/ikplugin
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
CPPFLAGS += -I../Expressions -I../Rasterizer -I../GameLogic
CPPFLAGS += -I../Ketsji -I../BlenderRoutines -I../SceneGraph
diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript
index 2d126310475..616c205732c 100644
--- a/source/gameengine/Converter/SConscript
+++ b/source/gameengine/Converter/SConscript
@@ -13,14 +13,23 @@ incs += ' #source/blender/blenlib #source/blender/blenkernel #source/blender'
incs += ' #source/blender/editors/include #source/blender/makesdna #source/gameengine/Rasterizer'
incs += ' #source/gameengine/Rasterizer/RAS_OpenGLRasterizer #source/gameengine/GameLogic'
incs += ' #source/gameengine/Expressions #source/gameengine/Network #source/gameengine/SceneGraph'
-incs += ' #source/gameengine/Physics/common #source/gameengine/Physics/Bullet #source/gameengine/Physics/BlOde'
+incs += ' #source/gameengine/Physics/common #source/gameengine/Physics/Bullet'
incs += ' #source/gameengine/Physics/Dummy'
incs += ' #source/gameengine/Network/LoopBackNetwork'
incs += ' #source/blender/misc #source/blender/blenloader #source/blender/gpu'
incs += ' #source/blender/windowmanager'
incs += ' #source/blender/makesrna'
+incs += ' #source/blender/ikplugin'
-incs += ' ' + env['BF_PYTHON_INC']
incs += ' ' + env['BF_BULLET_INC']
+if env['BF_DEBUG']:
+ if env['OURPLATFORM'] in ('win32-mingw', 'win32-vc', 'win64-vc'):
+ defs.append('_DEBUG')
+
+if env['WITH_BF_PYTHON']:
+ incs += ' ' + env['BF_PYTHON_INC']
+else:
+ defs.append('DISABLE_PYTHON')
+
env.BlenderLib ( 'bf_converter', sources, Split(incs), defs, libtype=['core','player'], priority=[305,40], cxx_compileflags=env['BGE_CXXFLAGS'])