1156 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1156 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* 
 | 
						|
 * $Id:
 | 
						|
 *
 | 
						|
 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
 | 
						|
 *
 | 
						|
 * This program is free software; you can redistribute it and/or
 | 
						|
 * modify it under the terms of the GNU General Public License
 | 
						|
 * as published by the Free Software Foundation; either version 2
 | 
						|
 * of the License, or (at your option) any later version. The Blender
 | 
						|
 * Foundation also sells licenses for use in proprietary software under
 | 
						|
 * the Blender License.  See http://www.blender.org/BL/ for information
 | 
						|
 * about this.
 | 
						|
 *
 | 
						|
 * 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.
 | 
						|
 *
 | 
						|
 * Contributor(s): Joseph Gilbert
 | 
						|
 *
 | 
						|
 * ***** END GPL/BL DUAL LICENSE BLOCK *****
 | 
						|
*/
 | 
						|
 | 
						|
#include "Pose.h"
 | 
						|
 | 
						|
 | 
						|
#include "mydevice.h"
 | 
						|
#include "BKE_armature.h"
 | 
						|
#include "BKE_main.h"
 | 
						|
#include "BKE_global.h"
 | 
						|
#include "BKE_action.h"
 | 
						|
#include "BKE_utildefines.h"
 | 
						|
#include "BIF_editaction.h"
 | 
						|
#include "BIF_space.h"
 | 
						|
#include "BIF_poseobject.h"
 | 
						|
#include "BKE_depsgraph.h"
 | 
						|
#include "DNA_object_types.h"
 | 
						|
#include "DNA_ipo_types.h"
 | 
						|
#include "DNA_scene_types.h"
 | 
						|
#include "DNA_space_types.h"	//1 - this order
 | 
						|
#include "BSE_editipo.h"			//2
 | 
						|
#include "BLI_blenlib.h"
 | 
						|
#include "BLI_arithb.h"
 | 
						|
#include "Mathutils.h"
 | 
						|
#include "Object.h"
 | 
						|
#include "Constraint.h"
 | 
						|
#include "NLA.h"
 | 
						|
#include "gen_utils.h"
 | 
						|
 | 
						|
#include "DNA_armature_types.h" /*used for pose bone select*/
 | 
						|
 | 
						|
extern void chan_calc_mat(bPoseChannel *chan);
 | 
						|
 | 
						|
//------------------------ERROR CODES---------------------------------
 | 
						|
//This is here just to make me happy and to have more consistant error strings :)
 | 
						|
static const char sPoseError[] = "Pose - Error: ";
 | 
						|
//static const char sPoseBadArgs[] = "Pose - Bad Arguments: ";
 | 
						|
static const char sPoseBoneError[] = "PoseBone - Error: ";
 | 
						|
//static const char sPoseBoneBadArgs[] = "PoseBone - Bad Arguments: ";
 | 
						|
static const char sPoseBonesDictError[] = "PoseBone - Error: ";
 | 
						|
//static const char sPoseBonesDictBadArgs[] = "PoseBone - Bad Arguments: ";
 | 
						|
 | 
						|
//################## PoseBonesDict_Type (internal) ########################
 | 
						|
/*This is an internal psuedo-dictionary type that allows for manipulation
 | 
						|
* of posechannels inside of a pose structure. It is a subobject of pose.
 | 
						|
* i.e. Pose.bones['key']*/
 | 
						|
//################################################################
 | 
						|
 | 
						|
//------------------METHOD IMPLEMENTATIONS-----------------------------
 | 
						|
//------------------------Pose.bones.items()
 | 
						|
//Returns a list of key:value pairs like dict.items()
 | 
						|
static PyObject* PoseBonesDict_items(BPy_PoseBonesDict *self)
 | 
						|
{
 | 
						|
	return PyDict_Items(self->bonesMap); 
 | 
						|
}
 | 
						|
//------------------------Pose.bones.keys()
 | 
						|
//Returns a list of keys like dict.keys()
 | 
						|
static PyObject* PoseBonesDict_keys(BPy_PoseBonesDict *self)
 | 
						|
{
 | 
						|
	return PyDict_Keys(self->bonesMap);
 | 
						|
}
 | 
						|
//------------------------Armature.bones.values()
 | 
						|
//Returns a list of values like dict.values()
 | 
						|
static PyObject* PoseBonesDict_values(BPy_PoseBonesDict *self)
 | 
						|
{
 | 
						|
	return PyDict_Values(self->bonesMap);
 | 
						|
}
 | 
						|
//------------------ATTRIBUTE IMPLEMENTATION---------------------------
 | 
						|
//------------------TYPE_OBECT IMPLEMENTATION-----------------------
 | 
						|
//------------------------tp_doc
 | 
						|
//The __doc__ string for this object
 | 
						|
static char BPy_PoseBonesDict_doc[] = "This is an internal subobject of pose\
 | 
						|
designed to act as a Py_PoseBone dictionary.";
 | 
						|
 | 
						|
//------------------------tp_methods
 | 
						|
//This contains a list of all methods the object contains
 | 
						|
static PyMethodDef BPy_PoseBonesDict_methods[] = {
 | 
						|
	{"items", (PyCFunction) PoseBonesDict_items, METH_NOARGS, 
 | 
						|
		"() - Returns the key:value pairs from the dictionary"},
 | 
						|
	{"keys", (PyCFunction) PoseBonesDict_keys, METH_NOARGS, 
 | 
						|
		"() - Returns the keys the dictionary"},
 | 
						|
	{"values", (PyCFunction) PoseBonesDict_values, METH_NOARGS, 
 | 
						|
		"() - Returns the values from the dictionary"},
 | 
						|
	{NULL, NULL, 0, NULL}
 | 
						|
};
 | 
						|
//-----------------(internal)
 | 
						|
static int PoseBoneMapping_Init(PyObject *dictionary, ListBase *posechannels){
 | 
						|
	bPoseChannel *pchan = NULL;
 | 
						|
	PyObject *py_posechannel = NULL;
 | 
						|
 | 
						|
	for (pchan = posechannels->first; pchan; pchan = pchan->next){
 | 
						|
		py_posechannel = PyPoseBone_FromPosechannel(pchan);
 | 
						|
		if (!py_posechannel)
 | 
						|
			return -1;
 | 
						|
 | 
						|
		if(PyDict_SetItemString(dictionary,
 | 
						|
					pchan->name, py_posechannel) == -1){
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
		Py_DECREF(py_posechannel);
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
//----------------- BonesDict_InitBones
 | 
						|
static int PoseBonesDict_InitBones(BPy_PoseBonesDict *self)
 | 
						|
{
 | 
						|
	PyDict_Clear(self->bonesMap);
 | 
						|
	if (PoseBoneMapping_Init(self->bonesMap, self->bones) == -1)
 | 
						|
		return 0;
 | 
						|
	return 1;
 | 
						|
} 
 | 
						|
 | 
						|
//------------------------tp_repr
 | 
						|
//This is the string representation of the object
 | 
						|
static PyObject *PoseBonesDict_repr(BPy_PoseBonesDict *self)
 | 
						|
{
 | 
						|
	char buffer[128], str[4096];
 | 
						|
	PyObject *key, *value;
 | 
						|
	int pos = 0;
 | 
						|
 | 
						|
	BLI_strncpy(str,"",4096);
 | 
						|
	sprintf(buffer, "[Pose Bone Dict: {");
 | 
						|
	strcat(str,buffer);
 | 
						|
	while (PyDict_Next(self->bonesMap, &pos, &key, &value)) {
 | 
						|
		sprintf(buffer, "%s : %s, ", PyString_AsString(key), 
 | 
						|
			PyString_AsString(value->ob_type->tp_repr(value)));
 | 
						|
		strcat(str,buffer);
 | 
						|
	}
 | 
						|
	sprintf(buffer, "}]\n");
 | 
						|
	strcat(str,buffer);
 | 
						|
	return PyString_FromString(str);
 | 
						|
}
 | 
						|
 | 
						|
//------------------------tp_dealloc
 | 
						|
//This tells how to 'tear-down' our object when ref count hits 0
 | 
						|
static void PoseBonesDict_dealloc(BPy_PoseBonesDict * self)
 | 
						|
{
 | 
						|
	Py_DECREF(self->bonesMap);
 | 
						|
	PoseBonesDict_Type.tp_free(self);
 | 
						|
	return;
 | 
						|
}
 | 
						|
//------------------------mp_length
 | 
						|
//This gets the size of the dictionary
 | 
						|
static int PoseBonesDict_len(BPy_PoseBonesDict *self)
 | 
						|
{
 | 
						|
	return BLI_countlist(self->bones);
 | 
						|
}
 | 
						|
//-----------------------mp_subscript
 | 
						|
//This defines getting a bone from the dictionary - x = Bones['key']
 | 
						|
static PyObject *PoseBonesDict_GetItem(BPy_PoseBonesDict *self, PyObject* key)
 | 
						|
{ 
 | 
						|
	PyObject *value = NULL;
 | 
						|
 | 
						|
	value = PyDict_GetItem(self->bonesMap, key);
 | 
						|
	if(value == NULL){
 | 
						|
        return EXPP_incr_ret(Py_None);
 | 
						|
	}
 | 
						|
	return EXPP_incr_ret(value);
 | 
						|
}
 | 
						|
//------------------TYPE_OBECT DEFINITION--------------------------
 | 
						|
//Mapping Protocol
 | 
						|
static PyMappingMethods PoseBonesDict_MapMethods = {
 | 
						|
	(inquiry) PoseBonesDict_len,					//mp_length
 | 
						|
	(binaryfunc)PoseBonesDict_GetItem,		//mp_subscript
 | 
						|
	0,														//mp_ass_subscript
 | 
						|
};
 | 
						|
//PoseBonesDict TypeObject
 | 
						|
PyTypeObject PoseBonesDict_Type = {
 | 
						|
	PyObject_HEAD_INIT(NULL)			//tp_head
 | 
						|
	0,												//tp_internal
 | 
						|
	"PoseBonesDict",								//tp_name
 | 
						|
	sizeof(BPy_PoseBonesDict),					//tp_basicsize
 | 
						|
	0,												//tp_itemsize
 | 
						|
	(destructor)PoseBonesDict_dealloc,		//tp_dealloc
 | 
						|
	0,												//tp_print
 | 
						|
	0,												//tp_getattr
 | 
						|
	0,												//tp_setattr
 | 
						|
	0,												//tp_compare
 | 
						|
	(reprfunc) PoseBonesDict_repr,				//tp_repr
 | 
						|
	0,												//tp_as_number
 | 
						|
	0,												//tp_as_sequence
 | 
						|
	&PoseBonesDict_MapMethods,				//tp_as_mapping
 | 
						|
	0,												//tp_hash
 | 
						|
	0,												//tp_call
 | 
						|
	0,												//tp_str
 | 
						|
	0,												//tp_getattro
 | 
						|
	0,												//tp_setattro
 | 
						|
	0,												//tp_as_buffer
 | 
						|
	Py_TPFLAGS_DEFAULT,					//tp_flags
 | 
						|
	BPy_PoseBonesDict_doc,						//tp_doc
 | 
						|
	0,												//tp_traverse
 | 
						|
	0,												//tp_clear
 | 
						|
	0,												//tp_richcompare
 | 
						|
	0,												//tp_weaklistoffset
 | 
						|
	0,												//tp_iter
 | 
						|
	0,												//tp_iternext
 | 
						|
	BPy_PoseBonesDict_methods,				//tp_methods
 | 
						|
	0,												//tp_members
 | 
						|
	0,												//tp_getset
 | 
						|
	0,												//tp_base
 | 
						|
	0,												//tp_dict
 | 
						|
	0,												//tp_descr_get
 | 
						|
	0,												//tp_descr_set
 | 
						|
	0,												//tp_dictoffset
 | 
						|
	0, 				                                //tp_init
 | 
						|
	0,												//tp_alloc
 | 
						|
	0,												//tp_new
 | 
						|
	0,												//tp_free
 | 
						|
	0,												//tp_is_gc
 | 
						|
	0,												//tp_bases
 | 
						|
	0,												//tp_mro
 | 
						|
	0,												//tp_cache
 | 
						|
	0,												//tp_subclasses
 | 
						|
	0,												//tp_weaklist
 | 
						|
	0												//tp_del
 | 
						|
};
 | 
						|
//-----------------------PyPoseBonesDict_FromPyPose
 | 
						|
static PyObject *PyPoseBonesDict_FromPyPose(BPy_Pose *py_pose)
 | 
						|
{
 | 
						|
	BPy_PoseBonesDict *py_posebonesdict = NULL;
 | 
						|
 | 
						|
	//create py object
 | 
						|
	py_posebonesdict = (BPy_PoseBonesDict *)PoseBonesDict_Type.tp_alloc(&PoseBonesDict_Type, 0); 
 | 
						|
	if (!py_posebonesdict)
 | 
						|
		goto RuntimeError;
 | 
						|
 | 
						|
	//create internal dictionaries
 | 
						|
	py_posebonesdict->bonesMap = PyDict_New();
 | 
						|
	if (!py_posebonesdict->bonesMap)
 | 
						|
		goto RuntimeError;
 | 
						|
 | 
						|
	//set listbase pointer
 | 
						|
	py_posebonesdict->bones = &py_pose->pose->chanbase;
 | 
						|
 | 
						|
	//now that everything is setup - init the mappings
 | 
						|
	if (!PoseBonesDict_InitBones(py_posebonesdict))
 | 
						|
		goto RuntimeError;
 | 
						|
 | 
						|
	return (PyObject*)py_posebonesdict;
 | 
						|
 | 
						|
RuntimeError:
 | 
						|
	return EXPP_objError(PyExc_RuntimeError, "%s%s", 
 | 
						|
		sPoseBonesDictError, "Failed to create class");
 | 
						|
}
 | 
						|
 | 
						|
//################## Pose_Type ##########################
 | 
						|
/*This type is a wrapper for a pose*/
 | 
						|
//####################################################
 | 
						|
//------------------METHOD IMPLEMENTATIONS------------------------------
 | 
						|
static PyObject *Pose_update(BPy_Pose *self)
 | 
						|
{
 | 
						|
	Object *daddy = NULL;
 | 
						|
 | 
						|
	self->pose->flag |= POSE_RECALC;
 | 
						|
 | 
						|
	for (daddy = G.main->object.first; daddy; daddy = daddy->id.next){
 | 
						|
		if (daddy->pose == self->pose){
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if(daddy)
 | 
						|
		where_is_pose(daddy);
 | 
						|
 | 
						|
	return EXPP_incr_ret(Py_None);
 | 
						|
}
 | 
						|
//------------------------tp_methods
 | 
						|
//This contains a list of all methods the object contains
 | 
						|
static PyMethodDef BPy_Pose_methods[] = {
 | 
						|
	{"update", (PyCFunction) Pose_update, METH_NOARGS, 
 | 
						|
		"() - Rebuilds the pose with new values"},
 | 
						|
	{NULL, NULL, 0, NULL}
 | 
						|
};
 | 
						|
//------------------ATTRIBUTE IMPLEMENTATIONS---------------------------
 | 
						|
//------------------------Pose.bones (getter)
 | 
						|
//Gets the bones attribute
 | 
						|
static PyObject *Pose_getBoneDict(BPy_Pose *self, void *closure)
 | 
						|
{
 | 
						|
    return EXPP_incr_ret((PyObject*)self->Bones);
 | 
						|
}
 | 
						|
//------------------------Pose.bones (setter)
 | 
						|
//Sets the bones attribute
 | 
						|
static int Pose_setBoneDict(BPy_Pose *self, PyObject *value, void *closure)
 | 
						|
{
 | 
						|
	goto AttributeError;
 | 
						|
 | 
						|
AttributeError:
 | 
						|
	return EXPP_intError(PyExc_AttributeError, "%s%s", 
 | 
						|
		sPoseError, "You are not allowed to change the .bones attribute");
 | 
						|
}
 | 
						|
//------------------TYPE_OBECT IMPLEMENTATION---------------------------
 | 
						|
//------------------------tp_getset
 | 
						|
//This contains methods for attributes that require checking
 | 
						|
static PyGetSetDef BPy_Pose_getset[] = {
 | 
						|
	{"bones", (getter)Pose_getBoneDict, (setter)Pose_setBoneDict, 
 | 
						|
		"The pose's Bone dictionary", NULL},
 | 
						|
	{NULL, NULL, NULL, NULL, NULL}
 | 
						|
};
 | 
						|
//------------------------tp_dealloc
 | 
						|
//This tells how to 'tear-down' our object when ref count hits 0
 | 
						|
static void Pose_dealloc(BPy_Pose *self)
 | 
						|
{
 | 
						|
	Py_DECREF(self->Bones);
 | 
						|
	Pose_Type.tp_free(self);
 | 
						|
	return;
 | 
						|
}
 | 
						|
//------------------------tp_cmp
 | 
						|
//This compares 2 pose types
 | 
						|
static int Pose_compare(BPy_Pose *a, BPy_Pose *b )
 | 
						|
{
 | 
						|
	return ( a->pose== b->pose ) ? 0 : -1;
 | 
						|
}
 | 
						|
//------------------------tp_repr
 | 
						|
//This is the string representation of the object
 | 
						|
static PyObject *Pose_repr(BPy_Pose *self)
 | 
						|
{
 | 
						|
	return PyString_FromFormat( "[Pose \"%s\"]", self->name); 
 | 
						|
}
 | 
						|
//------------------------tp_doc
 | 
						|
//The __doc__ string for this object
 | 
						|
static char BPy_Pose_doc[] = "This object wraps a Blender Pose object.";
 | 
						|
 | 
						|
//------------------TYPE_OBECT DEFINITION--------------------------
 | 
						|
PyTypeObject Pose_Type = {
 | 
						|
	PyObject_HEAD_INIT(NULL)   //tp_head
 | 
						|
	0,										//tp_internal
 | 
						|
	"Pose",								//tp_name
 | 
						|
	sizeof(BPy_Pose),					//tp_basicsize
 | 
						|
	0,										//tp_itemsize
 | 
						|
	(destructor)Pose_dealloc,		//tp_dealloc
 | 
						|
	0,										//tp_print
 | 
						|
	0,										//tp_getattr
 | 
						|
	0,										//tp_setattr
 | 
						|
	0,										//tp_compare
 | 
						|
	(reprfunc)Pose_repr,				//tp_repr
 | 
						|
	0,										//tp_as_number
 | 
						|
	0,										//tp_as_sequence
 | 
						|
	0,										//tp_as_mapping
 | 
						|
	0,										//tp_hash
 | 
						|
	0,										//tp_call
 | 
						|
	0,										//tp_str
 | 
						|
	0,										//tp_getattro
 | 
						|
	0,										//tp_setattro
 | 
						|
	0,										//tp_as_buffer
 | 
						|
	Py_TPFLAGS_DEFAULT,         //tp_flags
 | 
						|
	BPy_Pose_doc,					//tp_doc
 | 
						|
	0,										//tp_traverse
 | 
						|
	0,										//tp_clear
 | 
						|
	0,										//tp_richcompare
 | 
						|
	0,										//tp_weaklistoffset
 | 
						|
	0,										//tp_iter
 | 
						|
	0,										//tp_iternext
 | 
						|
	BPy_Pose_methods,				//tp_methods
 | 
						|
	0,										//tp_members
 | 
						|
	BPy_Pose_getset,					//tp_getset
 | 
						|
	0,										//tp_base
 | 
						|
	0,										//tp_dict
 | 
						|
	0,										//tp_descr_get
 | 
						|
	0,										//tp_descr_set
 | 
						|
	0,										//tp_dictoffset
 | 
						|
	0,										//tp_init
 | 
						|
	0,										//tp_alloc
 | 
						|
	0,										//tp_new
 | 
						|
	0,										//tp_free
 | 
						|
	0,										//tp_is_gc
 | 
						|
	0,										//tp_bases
 | 
						|
	0,										//tp_mro
 | 
						|
	0,										//tp_cache
 | 
						|
	0,										//tp_subclasses
 | 
						|
	0,										//tp_weaklist
 | 
						|
	0										//tp_del
 | 
						|
};
 | 
						|
//################## PoseBone_Type #####################
 | 
						|
/*This type is a wrapper for a posechannel*/
 | 
						|
//####################################################
 | 
						|
//------------------METHOD IMPLEMENTATIONS------------------------------
 | 
						|
//------------------------------PoseBone.insertKey()
 | 
						|
static PyObject *PoseBone_insertKey(BPy_PoseBone *self, PyObject *args)
 | 
						|
{
 | 
						|
	PyObject *parent_object = NULL;
 | 
						|
	PyObject *constants = NULL, *item = NULL;
 | 
						|
	int frame = 1, oldframe, length, x, numeric_value = 0, oldflag;
 | 
						|
	bPoseChannel *pchan = NULL;
 | 
						|
	
 | 
						|
 | 
						|
	if (!PyArg_ParseTuple(args, "O!i|O", &Object_Type, &parent_object, &frame, &constants ))
 | 
						|
		goto AttributeError;
 | 
						|
 | 
						|
	//verify that this pchannel is part of the object->pose
 | 
						|
	for (pchan = ((BPy_Object*)parent_object)->object->pose->chanbase.first; 
 | 
						|
		pchan; pchan = pchan->next){
 | 
						|
		if (pchan == self->posechannel)
 | 
						|
			break;
 | 
						|
	}
 | 
						|
	if (!pchan)
 | 
						|
		goto AttributeError2;
 | 
						|
 | 
						|
	//verify that there is an action bound to this object
 | 
						|
	if (!((BPy_Object*)parent_object)->object->action){
 | 
						|
		goto AttributeError5;
 | 
						|
	}
 | 
						|
 | 
						|
	oldflag = self->posechannel->flag;
 | 
						|
	self->posechannel->flag = 0;
 | 
						|
	//set the flags for this posechannel
 | 
						|
	if (constants){
 | 
						|
		if(PySequence_Check(constants)){
 | 
						|
			length = PySequence_Length(constants);
 | 
						|
			for (x = 0; x < length; x++){
 | 
						|
				item = PySequence_GetItem(constants, x);
 | 
						|
				if (item == EXPP_GetModuleConstant("Blender.Object.Pose", "ROT")){
 | 
						|
					numeric_value |= POSE_ROT;
 | 
						|
				}else if (item == EXPP_GetModuleConstant("Blender.Object.Pose", "LOC")){
 | 
						|
					numeric_value |= POSE_LOC;
 | 
						|
				}else if (item == EXPP_GetModuleConstant("Blender.Object.Pose", "SIZE")){
 | 
						|
					numeric_value |= POSE_SIZE;
 | 
						|
				}else{
 | 
						|
					Py_DECREF(item);
 | 
						|
					self->posechannel->flag = (short)oldflag;
 | 
						|
					goto AttributeError4;
 | 
						|
				}
 | 
						|
				Py_DECREF(item);
 | 
						|
			}
 | 
						|
			self->posechannel->flag = (short)numeric_value;
 | 
						|
		}else if (BPy_Constant_Check(constants)){
 | 
						|
			if (constants == EXPP_GetModuleConstant("Blender.Object.Pose", "ROT")){
 | 
						|
				numeric_value |= POSE_ROT;
 | 
						|
			}else if (constants == EXPP_GetModuleConstant("Blender.Object.Pose", "LOC")){
 | 
						|
				numeric_value |= POSE_LOC;
 | 
						|
			}else if (constants == EXPP_GetModuleConstant("Blender.Object.Pose", "SIZE")){
 | 
						|
				numeric_value |= POSE_SIZE;
 | 
						|
			}else{
 | 
						|
				self->posechannel->flag = (short)oldflag;
 | 
						|
				goto AttributeError4;
 | 
						|
			}
 | 
						|
			self->posechannel->flag = (short)numeric_value;
 | 
						|
		}else{
 | 
						|
			goto AttributeError3;
 | 
						|
		}
 | 
						|
	}else{ //nothing passed so set them all
 | 
						|
		self->posechannel->flag |= POSE_ROT;
 | 
						|
		self->posechannel->flag |= POSE_LOC;
 | 
						|
		self->posechannel->flag |= POSE_SIZE;
 | 
						|
	}
 | 
						|
 | 
						|
	//set the frame we want insertion on
 | 
						|
	oldframe = G.scene->r.cfra;
 | 
						|
	G.scene->r.cfra = frame;
 | 
						|
 | 
						|
	//add the action channel if it's not there
 | 
						|
	verify_action_channel(((BPy_Object*)parent_object)->object->action, 
 | 
						|
		self->posechannel->name);
 | 
						|
 | 
						|
	//insert the pose keys
 | 
						|
	if (self->posechannel->flag & POSE_ROT){
 | 
						|
		insertkey(&((BPy_Object*)parent_object)->object->id, 
 | 
						|
			ID_PO, self->posechannel->name, NULL, AC_QUAT_X);
 | 
						|
		insertkey(&((BPy_Object*)parent_object)->object->id, 
 | 
						|
			ID_PO, self->posechannel->name, NULL, AC_QUAT_Y);
 | 
						|
		insertkey(&((BPy_Object*)parent_object)->object->id, 
 | 
						|
			ID_PO, self->posechannel->name, NULL, AC_QUAT_Z);
 | 
						|
		insertkey(&((BPy_Object*)parent_object)->object->id, 
 | 
						|
			ID_PO, self->posechannel->name, NULL, AC_QUAT_W);
 | 
						|
	}
 | 
						|
	if (self->posechannel->flag & POSE_LOC){
 | 
						|
		insertkey(&((BPy_Object*)parent_object)->object->id, 
 | 
						|
			ID_PO, self->posechannel->name, NULL, AC_LOC_X);
 | 
						|
		insertkey(&((BPy_Object*)parent_object)->object->id, 
 | 
						|
			ID_PO, self->posechannel->name, NULL, AC_LOC_Y);
 | 
						|
		insertkey(&((BPy_Object*)parent_object)->object->id, 
 | 
						|
			ID_PO, self->posechannel->name, NULL, AC_LOC_Z);
 | 
						|
	}
 | 
						|
	if (self->posechannel->flag & POSE_SIZE){
 | 
						|
		insertkey(&((BPy_Object*)parent_object)->object->id, 
 | 
						|
			ID_PO, self->posechannel->name, NULL, AC_SIZE_X);
 | 
						|
		insertkey(&((BPy_Object*)parent_object)->object->id, 
 | 
						|
			ID_PO, self->posechannel->name, NULL, AC_SIZE_Y);
 | 
						|
		insertkey(&((BPy_Object*)parent_object)->object->id, 
 | 
						|
			ID_PO, self->posechannel->name, NULL, AC_SIZE_Z);
 | 
						|
	}
 | 
						|
 | 
						|
	//flip the frame back
 | 
						|
	G.scene->r.cfra = oldframe;
 | 
						|
 | 
						|
	//update the IPOs
 | 
						|
	remake_action_ipos (((BPy_Object*)parent_object)->object->action);
 | 
						|
 | 
						|
	return EXPP_incr_ret(Py_None);
 | 
						|
 | 
						|
AttributeError:
 | 
						|
	return EXPP_objError(PyExc_AttributeError, "%s%s%s",
 | 
						|
		sPoseBoneError, ".insertKey: ", "expects an Object, int, (optional) constants");
 | 
						|
AttributeError2:
 | 
						|
	return EXPP_objError(PyExc_AttributeError, "%s%s%s",
 | 
						|
		sPoseBoneError, ".insertKey: ", "wrong object detected. \
 | 
						|
		Use the object this pose came from");
 | 
						|
AttributeError3:
 | 
						|
	return EXPP_objError(PyExc_AttributeError, "%s%s%s",
 | 
						|
		sPoseBoneError, ".insertKey: ", "Expects a constant or list of constants");
 | 
						|
AttributeError4:
 | 
						|
	return EXPP_objError(PyExc_AttributeError, "%s%s%s",
 | 
						|
		sPoseBoneError, ".insertKey: ", "Please use a constant defined in the Pose module");
 | 
						|
AttributeError5:
 | 
						|
	return EXPP_objError(PyExc_AttributeError, "%s%s%s",
 | 
						|
		sPoseBoneError, ".insertKey: ", "You must set up and link an Action to this object first");
 | 
						|
}
 | 
						|
//------------------------tp_methods
 | 
						|
//This contains a list of all methods the object contains
 | 
						|
static PyMethodDef BPy_PoseBone_methods[] = {
 | 
						|
	{"insertKey", (PyCFunction) PoseBone_insertKey, METH_VARARGS, 
 | 
						|
		"() - insert a key for this pose into an action"},
 | 
						|
	{NULL, NULL, 0, NULL}
 | 
						|
};
 | 
						|
//------------------ATTRIBUTE IMPLEMENTATIONS---------------------------
 | 
						|
//------------------------PoseBone.name (getter)
 | 
						|
//Gets the name attribute
 | 
						|
static PyObject *PoseBone_getName(BPy_PoseBone *self, void *closure)
 | 
						|
{
 | 
						|
    return PyString_FromString(self->posechannel->name);
 | 
						|
}
 | 
						|
//------------------------PoseBone.name (setter)
 | 
						|
//Sets the name attribute
 | 
						|
static int PoseBone_setName(BPy_PoseBone *self, PyObject *value, void *closure)
 | 
						|
{
 | 
						|
	char *name = "";
 | 
						|
 | 
						|
	if (!PyArg_Parse(value, "s", &name))
 | 
						|
		goto AttributeError;
 | 
						|
 | 
						|
	BLI_strncpy(self->posechannel->name, name, 32);
 | 
						|
	return 0;
 | 
						|
 | 
						|
AttributeError:
 | 
						|
	return EXPP_intError(PyExc_AttributeError, "%s%s%s",
 | 
						|
		sPoseBoneError, ".name: ", "expects a string");
 | 
						|
}
 | 
						|
//------------------------PoseBone.loc (getter)
 | 
						|
//Gets the loc attribute
 | 
						|
static PyObject *PoseBone_getLoc(BPy_PoseBone *self, void *closure)
 | 
						|
{
 | 
						|
    return newVectorObject(self->posechannel->loc, 3, Py_WRAP);
 | 
						|
}
 | 
						|
//------------------------PoseBone.loc (setter)
 | 
						|
//Sets the loc attribute
 | 
						|
static int PoseBone_setLoc(BPy_PoseBone *self, PyObject *value, void *closure)
 | 
						|
{
 | 
						|
	VectorObject *vec = NULL;
 | 
						|
	int x;
 | 
						|
 | 
						|
	if (!PyArg_Parse(value, "O!", &vector_Type, &vec))
 | 
						|
		goto AttributeError;
 | 
						|
	if (vec->size != 3)
 | 
						|
		goto AttributeError;
 | 
						|
 | 
						|
	for (x = 0; x < 3; x++){
 | 
						|
		self->posechannel->loc[x] = vec->vec[x];
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
 | 
						|
AttributeError:
 | 
						|
	return EXPP_intError(PyExc_AttributeError, "%s%s%s",
 | 
						|
		sPoseBoneError, ".loc: ", "expects a 3d vector object");
 | 
						|
}
 | 
						|
//------------------------PoseBone.size (getter)
 | 
						|
//Gets the size attribute
 | 
						|
static PyObject *PoseBone_getSize(BPy_PoseBone *self, void *closure)
 | 
						|
{
 | 
						|
    return newVectorObject(self->posechannel->size, 3, Py_WRAP);
 | 
						|
}
 | 
						|
//------------------------PoseBone.size (setter)
 | 
						|
//Sets the size attribute
 | 
						|
static int PoseBone_setSize(BPy_PoseBone *self, PyObject *value, void *closure)
 | 
						|
{
 | 
						|
	VectorObject *vec = NULL;
 | 
						|
	int x;
 | 
						|
 | 
						|
	if (!PyArg_Parse(value, "O!", &vector_Type, &vec))
 | 
						|
		goto AttributeError;
 | 
						|
	if (vec->size != 3)
 | 
						|
		goto AttributeError;
 | 
						|
 | 
						|
	for (x = 0; x < 3; x++){
 | 
						|
		self->posechannel->size[x] = vec->vec[x];
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
 | 
						|
AttributeError:
 | 
						|
	return EXPP_intError(PyExc_AttributeError, "%s%s%s",
 | 
						|
		sPoseBoneError, ".size: ", "expects a 3d vector object");
 | 
						|
}
 | 
						|
//------------------------PoseBone.quat (getter)
 | 
						|
//Gets the quat attribute
 | 
						|
static PyObject *PoseBone_getQuat(BPy_PoseBone *self, void *closure)
 | 
						|
{
 | 
						|
    return newQuaternionObject(self->posechannel->quat, Py_WRAP);
 | 
						|
}
 | 
						|
//------------------------PoseBone.quat (setter)
 | 
						|
//Sets the quat attribute
 | 
						|
static int PoseBone_setQuat(BPy_PoseBone *self, PyObject *value, void *closure)
 | 
						|
{
 | 
						|
	QuaternionObject *quat = NULL;
 | 
						|
	int x;
 | 
						|
 | 
						|
	if (!PyArg_Parse(value, "O!", &quaternion_Type, &quat))
 | 
						|
		goto AttributeError;
 | 
						|
 | 
						|
	for (x = 0; x < 4; x++){
 | 
						|
		self->posechannel->quat[x] = quat->quat[x];
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
 | 
						|
AttributeError:
 | 
						|
	return EXPP_intError(PyExc_AttributeError, "%s%s%s",
 | 
						|
		sPoseBoneError, ".quat: ", "expects a quaternion object");
 | 
						|
}
 | 
						|
//------------------------PoseBone.localMatrix (getter)
 | 
						|
//Gets the chan_mat
 | 
						|
static PyObject *PoseBone_getLocalMatrix(BPy_PoseBone *self, void *closure)
 | 
						|
{
 | 
						|
    return newMatrixObject((float*)self->posechannel->chan_mat, 4, 4, Py_WRAP);
 | 
						|
}
 | 
						|
//------------------------PoseBone.localMatrix (setter)
 | 
						|
//Sets the chan_mat 
 | 
						|
static int PoseBone_setLocalMatrix(BPy_PoseBone *self, PyObject *value, void *closure)
 | 
						|
{
 | 
						|
	MatrixObject *matrix = NULL;
 | 
						|
	float size[3], quat[4], loc[3];
 | 
						|
	float mat3[3][3], mat4[4][4];
 | 
						|
	int matsize = 0;
 | 
						|
 | 
						|
	if (!PyArg_Parse(value, "O!", &matrix_Type, &matrix))
 | 
						|
		goto AttributeError;
 | 
						|
 | 
						|
	if (matrix->rowSize == 3 && matrix->colSize == 3){
 | 
						|
		matsize = 3;
 | 
						|
		Mat3CpyMat3(mat3, (float(*)[3])*matrix->matrix);
 | 
						|
	}else if (matrix->rowSize == 4 && matrix->colSize == 4){
 | 
						|
		matsize = 4;
 | 
						|
		Mat4CpyMat4(mat4, (float(*)[4])*matrix->matrix);
 | 
						|
	}
 | 
						|
 | 
						|
	if (matsize != 3 && matsize != 4){
 | 
						|
		goto AttributeError;
 | 
						|
	}
 | 
						|
 | 
						|
	//get size and rotation
 | 
						|
	if (matsize == 3){
 | 
						|
		Mat3ToSize(mat3, size);
 | 
						|
		Mat3Ortho(mat3);
 | 
						|
		Mat3ToQuat(mat3, quat);
 | 
						|
	}else if (matsize == 4){
 | 
						|
		Mat4ToSize(mat4, size);
 | 
						|
		Mat4Ortho(mat4);
 | 
						|
		Mat4ToQuat(mat4, quat);
 | 
						|
	}
 | 
						|
 | 
						|
	//get loc
 | 
						|
	if (matsize == 4){
 | 
						|
		VECCOPY(loc, matrix->matrix[3]);
 | 
						|
	}
 | 
						|
 | 
						|
	//copy new attributes
 | 
						|
	VECCOPY(self->posechannel->size, size);
 | 
						|
	QUATCOPY(self->posechannel->quat, quat);
 | 
						|
	if (matsize == 4){
 | 
						|
		VECCOPY(self->posechannel->loc, loc);
 | 
						|
	}
 | 
						|
 | 
						|
	//rebuild matrix
 | 
						|
	chan_calc_mat(self->posechannel);
 | 
						|
	return 0;
 | 
						|
 | 
						|
AttributeError:
 | 
						|
	return EXPP_intError(PyExc_AttributeError, "%s%s%s",
 | 
						|
		sPoseBoneError, ".localMatrix: ", "expects a 3x3 or 4x4 matrix object");
 | 
						|
}
 | 
						|
//------------------------PoseBone.poseMatrix (getter)
 | 
						|
//Gets the pose_mat
 | 
						|
static PyObject *PoseBone_getPoseMatrix(BPy_PoseBone *self, void *closure)
 | 
						|
{
 | 
						|
    return newMatrixObject((float*)self->posechannel->pose_mat, 4, 4, Py_WRAP);
 | 
						|
}
 | 
						|
//------------------------PoseBone.poseMatrix (setter)
 | 
						|
//Sets the pose_mat
 | 
						|
static int PoseBone_setPoseMatrix(BPy_PoseBone *self, PyObject *value, void *closure)
 | 
						|
{
 | 
						|
	return EXPP_intError(PyExc_AttributeError, "%s%s%s",
 | 
						|
		sPoseBoneError, ".poseMatrix: ", "not able to set this property");
 | 
						|
}
 | 
						|
//------------------------PoseBone.constraints (getter)
 | 
						|
//Gets the constraints sequence
 | 
						|
static PyObject *PoseBone_getConstraints(BPy_PoseBone *self, void *closure)
 | 
						|
{
 | 
						|
	return PoseConstraintSeq_CreatePyObject( self->posechannel );
 | 
						|
}
 | 
						|
//------------------------PoseBone.limitmin (getter)
 | 
						|
//Gets the pose bone limitmin value
 | 
						|
static PyObject *PoseBone_getLimitMin(BPy_PoseBone *self, void *closure)
 | 
						|
{
 | 
						|
	float mylimitmin[3];
 | 
						|
	Object *obj = NULL;
 | 
						|
 | 
						|
	obj = Object_FromPoseChannel(self->posechannel);
 | 
						|
	if (obj==NULL){
 | 
						|
		return EXPP_ReturnPyObjError(PyExc_AttributeError, "Bone data is not found");
 | 
						|
	}
 | 
						|
	mylimitmin[0]=0.0f;
 | 
						|
	mylimitmin[1]=0.0f;
 | 
						|
	mylimitmin[2]=0.0f;
 | 
						|
	if(pose_channel_in_IK_chain(obj, self->posechannel)){
 | 
						|
		if ((self->posechannel->ikflag & BONE_IK_NO_XDOF)==0) {
 | 
						|
			if ((self->posechannel->ikflag & BONE_IK_XLIMIT)) {
 | 
						|
				mylimitmin[0] = self->posechannel->limitmin[0];
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if ((self->posechannel->ikflag & BONE_IK_NO_YDOF)==0) {
 | 
						|
			if ((self->posechannel->ikflag & BONE_IK_YLIMIT)) {
 | 
						|
				mylimitmin[1] = self->posechannel->limitmin[1];
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if ((self->posechannel->ikflag & BONE_IK_NO_ZDOF)==0) {
 | 
						|
			if ((self->posechannel->ikflag & BONE_IK_ZLIMIT)) {
 | 
						|
				mylimitmin[2] = self->posechannel->limitmin[2];
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return newVectorObject(mylimitmin, 3, Py_NEW);
 | 
						|
}
 | 
						|
//------------------------PoseBone.limitmin (setter)
 | 
						|
//Sets the pose bone limitmin value
 | 
						|
static int PoseBone_setLimitMin(BPy_PoseBone *self, PyObject *value, void *closure)
 | 
						|
{
 | 
						|
	float newlimitmin[3];
 | 
						|
	int x;
 | 
						|
	Object *obj = NULL;
 | 
						|
	if(!PySequence_Check(value)){
 | 
						|
		return EXPP_ReturnIntError(PyExc_AttributeError, "Argument is not a sequence");
 | 
						|
	}
 | 
						|
	if (PySequence_Size(value) !=3){
 | 
						|
		return EXPP_ReturnIntError(PyExc_AttributeError, "Argument size must be 3");
 | 
						|
	}
 | 
						|
	newlimitmin[0]=0.0f;
 | 
						|
	newlimitmin[1]=0.0f;
 | 
						|
	newlimitmin[2]=0.0f;
 | 
						|
	for (x = 0; x<3;x++){
 | 
						|
		PyObject *item;
 | 
						|
		item = PySequence_GetItem(value, x); //new reference
 | 
						|
		if (PyFloat_Check(item)){
 | 
						|
			newlimitmin[x] = (float)PyFloat_AsDouble(item);
 | 
						|
		}else if (PyInt_Check(item)){
 | 
						|
			newlimitmin[x] = (float)PyInt_AsLong(item);
 | 
						|
		}
 | 
						|
		Py_DECREF(item);
 | 
						|
	}
 | 
						|
	obj = Object_FromPoseChannel(self->posechannel);
 | 
						|
	if (obj==NULL){
 | 
						|
		return EXPP_ReturnIntError(PyExc_AttributeError, "Bone data is not found");
 | 
						|
	}
 | 
						|
	if(!pose_channel_in_IK_chain(obj, self->posechannel)){
 | 
						|
		return EXPP_ReturnIntError(PyExc_AttributeError, "Bone is not part of an IK chain");
 | 
						|
	}
 | 
						|
	if ((self->posechannel->ikflag & BONE_IK_NO_XDOF)==0) {
 | 
						|
		if ((self->posechannel->ikflag & BONE_IK_XLIMIT)) {
 | 
						|
			self->posechannel->limitmin[0] = EXPP_ClampFloat(newlimitmin[0], -180.0f, 0.0f);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if ((self->posechannel->ikflag & BONE_IK_NO_YDOF)==0) {
 | 
						|
		if ((self->posechannel->ikflag & BONE_IK_YLIMIT)) {
 | 
						|
			self->posechannel->limitmin[1] = EXPP_ClampFloat(newlimitmin[1], -180.0f, 0.0f);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if ((self->posechannel->ikflag & BONE_IK_NO_ZDOF)==0) {
 | 
						|
		if ((self->posechannel->ikflag & BONE_IK_ZLIMIT)) {
 | 
						|
			self->posechannel->limitmin[2] = EXPP_ClampFloat(newlimitmin[2], -180.0f, 0.0f);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	DAG_object_flush_update(G.scene, obj, OB_RECALC_DATA);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
//------------------------PoseBone.limitmax (getter)
 | 
						|
//Gets the pose bone limitmax value
 | 
						|
static PyObject *PoseBone_getLimitMax(BPy_PoseBone *self, void *closure)
 | 
						|
{
 | 
						|
	float mylimitmax[3];
 | 
						|
	Object *obj = NULL;
 | 
						|
 | 
						|
	obj = Object_FromPoseChannel(self->posechannel);
 | 
						|
	if (obj==NULL){
 | 
						|
		return EXPP_ReturnPyObjError(PyExc_AttributeError, "Bone data is not found");
 | 
						|
	}
 | 
						|
	mylimitmax[0]=0.0f;
 | 
						|
	mylimitmax[1]=0.0f;
 | 
						|
	mylimitmax[2]=0.0f;
 | 
						|
	if(pose_channel_in_IK_chain(obj, self->posechannel)){
 | 
						|
		if ((self->posechannel->ikflag & BONE_IK_NO_XDOF)==0) {
 | 
						|
			if ((self->posechannel->ikflag & BONE_IK_XLIMIT)) {
 | 
						|
				mylimitmax[0] = self->posechannel->limitmax[0];
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if ((self->posechannel->ikflag & BONE_IK_NO_YDOF)==0) {
 | 
						|
			if ((self->posechannel->ikflag & BONE_IK_YLIMIT)) {
 | 
						|
				mylimitmax[1] = self->posechannel->limitmax[1];
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if ((self->posechannel->ikflag & BONE_IK_NO_ZDOF)==0) {
 | 
						|
			if ((self->posechannel->ikflag & BONE_IK_ZLIMIT)) {
 | 
						|
				mylimitmax[2] = self->posechannel->limitmax[2];
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return newVectorObject(mylimitmax, 3, Py_NEW);
 | 
						|
}
 | 
						|
//------------------------PoseBone.limitmax (setter)
 | 
						|
//Sets the pose bone limitmax value
 | 
						|
static int PoseBone_setLimitMax(BPy_PoseBone *self, PyObject *value, void *closure)
 | 
						|
{
 | 
						|
	float newlimitmax[3];
 | 
						|
	int x;
 | 
						|
	Object *obj = NULL;
 | 
						|
	if(!PySequence_Check(value)){
 | 
						|
		return EXPP_ReturnIntError(PyExc_AttributeError, "Argument is not a sequence");
 | 
						|
	}
 | 
						|
	if (PySequence_Size(value) !=3){
 | 
						|
		return EXPP_ReturnIntError(PyExc_AttributeError, "Argument size must be 3");
 | 
						|
	}
 | 
						|
	newlimitmax[0]=0.0f;
 | 
						|
	newlimitmax[1]=0.0f;
 | 
						|
	newlimitmax[2]=0.0f;
 | 
						|
	for (x = 0; x<3;x++){
 | 
						|
		PyObject *item;
 | 
						|
		item = PySequence_GetItem(value, x); //new reference
 | 
						|
		if (PyFloat_Check(item)){
 | 
						|
			newlimitmax[x] = (float)PyFloat_AsDouble(item);
 | 
						|
		}else if (PyInt_Check(item)){
 | 
						|
			newlimitmax[x] = (float)PyInt_AsLong(item);
 | 
						|
		}
 | 
						|
		Py_DECREF(item);
 | 
						|
	}
 | 
						|
	obj = Object_FromPoseChannel(self->posechannel);
 | 
						|
	if (obj==NULL){
 | 
						|
		return EXPP_ReturnIntError(PyExc_AttributeError, "Bone data is not found");
 | 
						|
	}
 | 
						|
	if(!pose_channel_in_IK_chain(obj, self->posechannel)){
 | 
						|
		return EXPP_ReturnIntError(PyExc_AttributeError, "Bone is not part of an IK chain");
 | 
						|
	}
 | 
						|
	if ((self->posechannel->ikflag & BONE_IK_NO_XDOF)==0) {
 | 
						|
		if ((self->posechannel->ikflag & BONE_IK_XLIMIT)) {
 | 
						|
			self->posechannel->limitmax[0] = EXPP_ClampFloat(newlimitmax[0], 0.0f, 180.0f);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if ((self->posechannel->ikflag & BONE_IK_NO_YDOF)==0) {
 | 
						|
		if ((self->posechannel->ikflag & BONE_IK_YLIMIT)) {
 | 
						|
			self->posechannel->limitmax[1] = EXPP_ClampFloat(newlimitmax[1], 0.0f, 180.0f);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if ((self->posechannel->ikflag & BONE_IK_NO_ZDOF)==0) {
 | 
						|
		if ((self->posechannel->ikflag & BONE_IK_ZLIMIT)) {
 | 
						|
			self->posechannel->limitmax[2] = EXPP_ClampFloat(newlimitmax[2], 0.0f, 180.0f);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	DAG_object_flush_update(G.scene, obj, OB_RECALC_DATA);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
//------------------------PoseBone.head (getter)
 | 
						|
//Gets the pose head position
 | 
						|
static PyObject *PoseBone_getHead(BPy_PoseBone *self, void *closure)
 | 
						|
{
 | 
						|
    return newVectorObject(self->posechannel->pose_head, 3, Py_NEW);
 | 
						|
}
 | 
						|
//------------------------PoseBone.head (setter)
 | 
						|
//Sets the pose head position
 | 
						|
static int PoseBone_setHead(BPy_PoseBone *self, PyObject *value, void *closure)
 | 
						|
{
 | 
						|
	return EXPP_intError(PyExc_AttributeError, "%s%s%s",
 | 
						|
		sPoseBoneError, ".head: ", "not able to set this property");
 | 
						|
}
 | 
						|
//------------------------PoseBone.tail (getter)
 | 
						|
//Gets the pose tail position
 | 
						|
static PyObject *PoseBone_getTail(BPy_PoseBone *self, void *closure)
 | 
						|
{
 | 
						|
    return newVectorObject(self->posechannel->pose_tail, 3, Py_NEW);
 | 
						|
}
 | 
						|
//------------------------PoseBone.tail (setter)
 | 
						|
//Sets the pose tail position
 | 
						|
static int PoseBone_setTail(BPy_PoseBone *self, PyObject *value, void *closure)
 | 
						|
{
 | 
						|
	return EXPP_intError(PyExc_AttributeError, "%s%s%s",
 | 
						|
		sPoseBoneError, ".tail: ", "not able to set this property");
 | 
						|
}
 | 
						|
//------------------------PoseBone.sel (getter)
 | 
						|
//Gets the pose bones selection
 | 
						|
static PyObject *PoseBone_getSelect(BPy_PoseBone *self, void *closure)
 | 
						|
{
 | 
						|
	if (self->posechannel->bone->flag & BONE_SELECTED)
 | 
						|
		Py_RETURN_TRUE;
 | 
						|
	else
 | 
						|
		Py_RETURN_FALSE;
 | 
						|
}
 | 
						|
//------------------------PoseBone.sel (setter)
 | 
						|
//Sets the pose bones selection
 | 
						|
static int PoseBone_setSelect(BPy_PoseBone *self, PyObject *value, void *closure)
 | 
						|
{
 | 
						|
	if (PyObject_IsTrue( value ))
 | 
						|
		self->posechannel->bone->flag |= BONE_SELECTED;
 | 
						|
	else
 | 
						|
		self->posechannel->bone->flag &= ~(BONE_SELECTED | BONE_ACTIVE);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//------------------------PoseBone.parent (getter)
 | 
						|
//Gets the pose bones selection
 | 
						|
static PyObject *PoseBone_getParent(BPy_PoseBone *self, void *closure)
 | 
						|
{
 | 
						|
	if (self->posechannel->parent) {
 | 
						|
		return PyPoseBone_FromPosechannel(self->posechannel->parent);
 | 
						|
	} else {
 | 
						|
        return EXPP_incr_ret(Py_None);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
//------------------TYPE_OBECT IMPLEMENTATION---------------------------
 | 
						|
//------------------------tp_getset
 | 
						|
//This contains methods for attributes that require checking
 | 
						|
static PyGetSetDef BPy_PoseBone_getset[] = {
 | 
						|
	{"name", (getter)PoseBone_getName, (setter)PoseBone_setName, 
 | 
						|
		"The pose bone's name", NULL},
 | 
						|
	{"loc", (getter)PoseBone_getLoc, (setter)PoseBone_setLoc, 
 | 
						|
		"The pose bone's change in location as a vector", NULL},
 | 
						|
	{"size", (getter)PoseBone_getSize, (setter)PoseBone_setSize, 
 | 
						|
		"The pose bone's change in size as a vector", NULL},
 | 
						|
	{"quat", (getter)PoseBone_getQuat, (setter)PoseBone_setQuat, 
 | 
						|
		"The pose bone's change in rotation as a quat", NULL},
 | 
						|
	{"localMatrix", (getter)PoseBone_getLocalMatrix, (setter)PoseBone_setLocalMatrix, 
 | 
						|
		"The pose bone's change matrix built from the quat, loc, and size", NULL},
 | 
						|
	{"poseMatrix", (getter)PoseBone_getPoseMatrix, (setter)PoseBone_setPoseMatrix, 
 | 
						|
		"The pose bone's matrix", NULL},
 | 
						|
	{"head", (getter)PoseBone_getHead, (setter)PoseBone_setHead, 
 | 
						|
		"The pose bone's head positon", NULL},
 | 
						|
	{"tail", (getter)PoseBone_getTail, (setter)PoseBone_setTail, 
 | 
						|
		"The pose bone's tail positon", NULL},
 | 
						|
	{"sel", (getter)PoseBone_getSelect, (setter)PoseBone_setSelect, 
 | 
						|
		"The pose selection state", NULL},
 | 
						|
    {"limitMin", (getter)PoseBone_getLimitMin, (setter)PoseBone_setLimitMin,
 | 
						|
        "The pose bone dof min", NULL},
 | 
						|
    {"limitMax", (getter)PoseBone_getLimitMax, (setter)PoseBone_setLimitMax,
 | 
						|
        "The pose bone dof max", NULL},
 | 
						|
	{"constraints", (getter)PoseBone_getConstraints, (setter)NULL, 
 | 
						|
		"The list of contraints that pertain to this pose bone", NULL},
 | 
						|
	{"parent", (getter)PoseBone_getParent, (setter)NULL, 
 | 
						|
		"The bones parent (read only for posebones)", NULL},
 | 
						|
	{NULL, NULL, NULL, NULL, NULL}
 | 
						|
};
 | 
						|
//------------------------tp_dealloc
 | 
						|
//This tells how to 'tear-down' our object when ref count hits 0
 | 
						|
static void PoseBone_dealloc(BPy_PoseBone *self)
 | 
						|
{
 | 
						|
	PoseBone_Type.tp_free(self);
 | 
						|
	return;
 | 
						|
}
 | 
						|
//------------------------tp_repr
 | 
						|
//This is the string representation of the object
 | 
						|
static PyObject *PoseBone_repr(BPy_PoseBone *self)
 | 
						|
{
 | 
						|
	return PyString_FromFormat( "[PoseBone \"%s\"]", self->posechannel->name); 
 | 
						|
}
 | 
						|
//------------------------tp_doc
 | 
						|
//The __doc__ string for this object
 | 
						|
static char BPy_PoseBone_doc[] = "This object wraps a Blender PoseBone object.";
 | 
						|
 | 
						|
//------------------TYPE_OBECT DEFINITION--------------------------
 | 
						|
PyTypeObject PoseBone_Type = {
 | 
						|
	PyObject_HEAD_INIT(NULL)   //tp_head
 | 
						|
	0,										//tp_internal
 | 
						|
	"PoseBone",							//tp_name
 | 
						|
	sizeof(BPy_PoseBone),			//tp_basicsize
 | 
						|
	0,										//tp_itemsize
 | 
						|
	(destructor)PoseBone_dealloc,		//tp_dealloc
 | 
						|
	0,										//tp_print
 | 
						|
	0,										//tp_getattr
 | 
						|
	0,										//tp_setattr
 | 
						|
	0,										//tp_compare
 | 
						|
	(reprfunc)PoseBone_repr,		//tp_repr
 | 
						|
	0,										//tp_as_number
 | 
						|
	0,										//tp_as_sequence
 | 
						|
	0,										//tp_as_mapping
 | 
						|
	0,										//tp_hash
 | 
						|
	0,										//tp_call
 | 
						|
	0,										//tp_str
 | 
						|
	0,										//tp_getattro
 | 
						|
	0,										//tp_setattro
 | 
						|
	0,										//tp_as_buffer
 | 
						|
	Py_TPFLAGS_DEFAULT,         //tp_flags
 | 
						|
	BPy_PoseBone_doc,				//tp_doc
 | 
						|
	0,										//tp_traverse
 | 
						|
	0,										//tp_clear
 | 
						|
	0,										//tp_richcompare
 | 
						|
	0,										//tp_weaklistoffset
 | 
						|
	0,										//tp_iter
 | 
						|
	0,										//tp_iternext
 | 
						|
	BPy_PoseBone_methods,		//tp_methods
 | 
						|
	0,										//tp_members
 | 
						|
	BPy_PoseBone_getset,			//tp_getset
 | 
						|
	0,										//tp_base
 | 
						|
	0,										//tp_dict
 | 
						|
	0,										//tp_descr_get
 | 
						|
	0,										//tp_descr_set
 | 
						|
	0,										//tp_dictoffset
 | 
						|
	0,										//tp_init
 | 
						|
	0,										//tp_alloc
 | 
						|
	0,										//tp_new
 | 
						|
	0,										//tp_free
 | 
						|
	0,										//tp_is_gc
 | 
						|
	0,										//tp_bases
 | 
						|
	0,										//tp_mro
 | 
						|
	0,										//tp_cache
 | 
						|
	0,										//tp_subclasses
 | 
						|
	0,										//tp_weaklist
 | 
						|
	0										//tp_del
 | 
						|
};
 | 
						|
//-------------------MODULE METHODS IMPLEMENTATION------------------------
 | 
						|
//-------------------MODULE METHODS DEFINITION-----------------------------
 | 
						|
struct PyMethodDef M_Pose_methods[] = {
 | 
						|
	{NULL, NULL, 0, NULL}
 | 
						|
};
 | 
						|
//-------------------MODULE INITIALIZATION--------------------------------
 | 
						|
PyObject *Pose_Init(void)
 | 
						|
{
 | 
						|
	PyObject *module;
 | 
						|
 | 
						|
	//Initializes TypeObject.ob_type
 | 
						|
	if (PyType_Ready(&Pose_Type) < 0 || PyType_Ready(&PoseBone_Type)  < 0 ||
 | 
						|
		PyType_Ready(&PoseBonesDict_Type) < 0) {
 | 
						|
		return EXPP_incr_ret(Py_None);
 | 
						|
	}
 | 
						|
 | 
						|
	//Register the module
 | 
						|
	module = Py_InitModule3("Blender.Object.Pose", M_Pose_methods, 
 | 
						|
		"The Blender Pose module"); 
 | 
						|
 | 
						|
	//Add TYPEOBJECTS to the module
 | 
						|
	PyModule_AddObject(module, "Pose", 
 | 
						|
		EXPP_incr_ret((PyObject *)&Pose_Type)); //*steals*
 | 
						|
	PyModule_AddObject(module, "PoseBone", 
 | 
						|
		EXPP_incr_ret((PyObject *)&PoseBone_Type)); //*steals*
 | 
						|
 | 
						|
	//Add CONSTANTS to the module
 | 
						|
	PyModule_AddObject(module, "ROT", 
 | 
						|
		EXPP_incr_ret(PyConstant_NewInt("ROT", POSE_ROT)));
 | 
						|
	PyModule_AddObject(module, "LOC", 
 | 
						|
		EXPP_incr_ret(PyConstant_NewInt("LOC", POSE_LOC)));
 | 
						|
	PyModule_AddObject(module, "SIZE", 
 | 
						|
		EXPP_incr_ret(PyConstant_NewInt("SIZE", POSE_SIZE)));
 | 
						|
 | 
						|
	return module;
 | 
						|
}
 | 
						|
//------------------VISIBLE PROTOTYPE IMPLEMENTATION-----------------------
 | 
						|
//------------------------------PyPose_FromPose (internal)
 | 
						|
//Returns a PyPose from a bPose - return PyNone if bPose is NULL
 | 
						|
PyObject *PyPose_FromPose(bPose *pose, char *name)
 | 
						|
{
 | 
						|
	BPy_Pose *py_pose = NULL;
 | 
						|
 | 
						|
	if (pose){
 | 
						|
		py_pose = (BPy_Pose*)Pose_Type.tp_alloc(&Pose_Type, 0);
 | 
						|
		if (!py_pose)
 | 
						|
			goto RuntimeError;
 | 
						|
 | 
						|
		py_pose->pose = pose;
 | 
						|
		BLI_strncpy(py_pose->name, name, 24);
 | 
						|
 | 
						|
		//create armature.bones
 | 
						|
		py_pose->Bones = (BPy_PoseBonesDict*)PyPoseBonesDict_FromPyPose(py_pose);
 | 
						|
		if (!py_pose->Bones)
 | 
						|
			goto RuntimeError;
 | 
						|
 | 
						|
		return (PyObject*)py_pose;
 | 
						|
	}else{
 | 
						|
		return EXPP_incr_ret(Py_None);
 | 
						|
	}
 | 
						|
 | 
						|
RuntimeError:
 | 
						|
	return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
 | 
						|
		sPoseError, "PyPose_FromPose: ", "Internal Error Ocurred");
 | 
						|
}
 | 
						|
//------------------------------PyPoseBone_FromPosechannel (internal)
 | 
						|
//Returns a PyPoseBone from a bPoseChannel - return PyNone if bPoseChannel is NULL
 | 
						|
PyObject *PyPoseBone_FromPosechannel(bPoseChannel *pchan)
 | 
						|
{
 | 
						|
	BPy_PoseBone *py_posechannel = NULL;
 | 
						|
 | 
						|
	if (pchan){
 | 
						|
		py_posechannel = (BPy_PoseBone*)PoseBone_Type.tp_alloc(&PoseBone_Type, 0);
 | 
						|
		if (!py_posechannel)
 | 
						|
			goto RuntimeError;
 | 
						|
		py_posechannel->posechannel = pchan;
 | 
						|
		return (PyObject*)py_posechannel;
 | 
						|
	}else{
 | 
						|
		return EXPP_incr_ret(Py_None);
 | 
						|
	}
 | 
						|
 | 
						|
RuntimeError:
 | 
						|
	return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
 | 
						|
		sPoseBoneError, "PyPoseBone_FromPosechannel: ", "Internal Error Ocurred");
 | 
						|
}
 | 
						|
//------------------------------Object_FromPoseChannel (internal)
 | 
						|
//An ugly method for determining where the pchan chame from
 | 
						|
Object *Object_FromPoseChannel(bPoseChannel *curr_pchan)
 | 
						|
{
 | 
						|
	int success = 0;
 | 
						|
	Object *obj = NULL;
 | 
						|
	bPoseChannel *pchan = NULL;
 | 
						|
	for(obj = G.main->object.first; obj; obj = obj->id.next){
 | 
						|
		if (obj->pose){
 | 
						|
			for (pchan = obj->pose->chanbase.first; pchan; pchan = pchan->next){
 | 
						|
				if (curr_pchan == pchan){
 | 
						|
					success = 1;
 | 
						|
					break;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			if (success)
 | 
						|
				break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return obj;
 | 
						|
}
 |