BGE PyAPI
while making a demo of using python to control bones found some more problems. also added channelNames attribute to BL_ActionActuator to get a list of valid channels to use. demo: http://www.graphicall.org/ftp/ideasman42/armature_python.blend its still not that useful since theres not way to know rest bone locations yet but better then nothing.
This commit is contained in:
@@ -777,6 +777,10 @@ PyObject* BL_ActionActuator::PyGetChannel(PyObject* value) {
|
||||
|
||||
bPoseChannel *pchan;
|
||||
|
||||
if(m_userpose==NULL && m_pose==NULL) {
|
||||
BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
|
||||
obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
|
||||
}
|
||||
|
||||
// get_pose_channel accounts for NULL pose, run on both incase one exists but
|
||||
// the channel doesnt
|
||||
@@ -922,14 +926,18 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel,
|
||||
obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
|
||||
|
||||
if (!m_userpose) {
|
||||
obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
|
||||
if(!m_pose)
|
||||
obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
|
||||
game_copy_pose(&m_userpose, m_pose);
|
||||
}
|
||||
pchan= verify_pose_channel(m_userpose, string); // adds the channel if its not there.
|
||||
//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.
|
||||
|
||||
VECCOPY (pchan->loc, matrix[3]);
|
||||
Mat4ToSize(matrix, pchan->size);
|
||||
Mat4ToQuat(matrix, pchan->quat);
|
||||
if (pchan) {
|
||||
VECCOPY (pchan->loc, matrix[3]);
|
||||
Mat4ToSize(matrix, pchan->size);
|
||||
Mat4ToQuat(matrix, pchan->quat);
|
||||
}
|
||||
}
|
||||
else {
|
||||
MT_Vector3 loc;
|
||||
@@ -941,15 +949,24 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel,
|
||||
|
||||
// same as above
|
||||
if (!m_userpose) {
|
||||
obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
|
||||
if(!m_pose)
|
||||
obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
|
||||
game_copy_pose(&m_userpose, m_pose);
|
||||
}
|
||||
pchan= verify_pose_channel(m_userpose, string);
|
||||
//pchan= verify_pose_channel(m_userpose, string); // adds the channel if its not there.
|
||||
pchan= get_pose_channel(m_userpose, string);
|
||||
|
||||
// for some reason loc.setValue(pchan->loc) fails
|
||||
pchan->loc[0]= loc[0]; pchan->loc[1]= loc[1]; pchan->loc[2]= loc[2];
|
||||
pchan->size[0]= size[0]; pchan->size[1]= size[1]; pchan->size[2]= size[2];
|
||||
pchan->quat[0]= quat[0]; pchan->quat[1]= quat[1]; pchan->quat[2]= quat[2]; pchan->quat[3]= quat[3];
|
||||
if(pchan) {
|
||||
pchan->loc[0]= loc[0]; pchan->loc[1]= loc[1]; pchan->loc[2]= loc[2];
|
||||
pchan->size[0]= size[0]; pchan->size[1]= size[1]; pchan->size[2]= size[2];
|
||||
pchan->quat[0]= quat[0]; pchan->quat[1]= quat[1]; pchan->quat[2]= quat[2]; pchan->quat[3]= quat[3];
|
||||
}
|
||||
}
|
||||
|
||||
if(pchan==NULL) {
|
||||
PyErr_SetString(PyExc_ValueError, "Channel could not be found, use the 'channelNames' attribute to get a list of valid channels");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pchan->flag |= POSE_ROT|POSE_LOC|POSE_SIZE;
|
||||
@@ -1027,6 +1044,7 @@ PyAttributeDef BL_ActionActuator::Attributes[] = {
|
||||
KX_PYATTRIBUTE_FLOAT_RW("frameEnd", 0, MAXFRAMEF, BL_ActionActuator, m_endframe),
|
||||
KX_PYATTRIBUTE_FLOAT_RW("blendIn", 0, MAXFRAMEF, BL_ActionActuator, m_blendin),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("action", BL_ActionActuator, pyattr_get_action, pyattr_set_action),
|
||||
KX_PYATTRIBUTE_RO_FUNCTION("channelNames", BL_ActionActuator, pyattr_get_channel_names),
|
||||
KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ActionActuator, m_priority),
|
||||
KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ActionActuator, m_localtime, CheckFrame),
|
||||
KX_PYATTRIBUTE_STRING_RW("propName", 0, 31, false, BL_ActionActuator, m_propname),
|
||||
@@ -1083,3 +1101,20 @@ int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF
|
||||
return PY_SET_ATTR_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
PyObject* BL_ActionActuator::pyattr_get_channel_names(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
|
||||
{
|
||||
BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
|
||||
PyObject *ret= PyList_New(0);
|
||||
|
||||
bPose *pose= ((BL_ArmatureObject*)self->GetParent())->GetOrigPose();
|
||||
|
||||
if(pose) {
|
||||
bPoseChannel *pchan;
|
||||
for(pchan= (bPoseChannel *)pose->chanbase.first; pchan; pchan= (bPoseChannel *)pchan->next) {
|
||||
PyList_Append(ret, PyString_FromString(pchan->name));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
|
||||
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);
|
||||
|
||||
static PyObject* pyattr_get_channel_names(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
|
||||
/* attribute check */
|
||||
static int CheckFrame(void *self, const PyAttributeDef*)
|
||||
{
|
||||
|
||||
@@ -59,6 +59,7 @@ public:
|
||||
void GetMRDPose(struct bPose **pose);
|
||||
void GetPose(struct bPose **pose);
|
||||
void SetPose (struct bPose *pose);
|
||||
struct bPose *GetOrigPose() {return m_pose;} // never edit this, only for accessing names
|
||||
|
||||
void ApplyPose();
|
||||
void RestorePose();
|
||||
|
||||
@@ -310,6 +310,8 @@ class BL_ActionActuator(SCA_IActuator):
|
||||
|
||||
@ivar action: The name of the action to set as the current action.
|
||||
@type action: string
|
||||
@ivar channelNames: A list of channel names that may be used with L{setChannel} and L{getChannel}
|
||||
@type channelNames: list of strings
|
||||
@ivar frameStart: Specifies the starting frame of the animation.
|
||||
@type frameStart: float
|
||||
@ivar frameEnd: Specifies the ending frame of the animation.
|
||||
@@ -340,7 +342,8 @@ class BL_ActionActuator(SCA_IActuator):
|
||||
"""
|
||||
Alternative to the 2 arguments, 4 arguments (channel, matrix, loc, size, quat) are also supported.
|
||||
|
||||
@param channel: A string specifying the name of the bone channel, created if missing.
|
||||
@note: These values are relative to the bones rest position, currently the api has no way to get this info (which is annoying), but can be worked around by using bones with a rest pose that has no translation.
|
||||
@param channel: A string specifying the name of the bone channel, error raised if not in L{channelNames}.
|
||||
@type channel: string
|
||||
@param matrix: A 4x4 matrix specifying the overriding transformation
|
||||
as an offset from the bone's rest position.
|
||||
@@ -349,7 +352,7 @@ class BL_ActionActuator(SCA_IActuator):
|
||||
|
||||
def getChannel(channel):
|
||||
"""
|
||||
@param channel: A string specifying the name of the bone channel. error raised if missing.
|
||||
@param channel: A string specifying the name of the bone channel. error raised if not in L{channelNames}.
|
||||
@type channel: string
|
||||
@rtype: tuple
|
||||
@return: (loc, size, quat)
|
||||
|
||||
Reference in New Issue
Block a user