Merged changes in the trunk up to revision 34670.

This commit is contained in:
2011-02-06 18:05:05 +00:00
232 changed files with 4940 additions and 3106 deletions

View File

@@ -37,6 +37,8 @@
* - Mathutils.Slerp --> quat.slerp(other, fac)
* - Mathutils.Rand: removed, use pythons random module
* - Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args
* - Mathutils.OrthoProjectionMatrix(plane, size, axis) --> Mathutils.OrthoProjectionMatrix(axis, size); merge axis & plane args
* - Mathutils.ShearMatrix(plane, factor, size) --> Mathutils.ShearMatrix(plane, size, factor); swap size & factor args, match other constructors.
* - Matrix.scalePart --> Matrix.scale_part
* - Matrix.translationPart --> Matrix.translation_part
* - Matrix.rotationPart --> Matrix.rotation_part
@@ -45,10 +47,24 @@
* - toEuler --> to_euler
* - toQuat --> to_quat
* - Vector.toTrackQuat --> Vector.to_track_quat
* - Vector.rotate(axis, angle) --> rotate(other), where other can be Euler/Quaternion/Matrix.
* - Quaternion * Quaternion --> cross product (not dot product)
* - Euler.rotate(angle, axis) --> Euler.rotate_axis(axis, angle)
* - Euler.unique() *removed*, not a standard function only toggled different rotations.
*
* - Matrix.rotation_part() -> to_3x3()
* - Matrix.scale_part() -> to_scale()
* - Matrix.translation_part() -> to_translation()
* - Matrix.resize4x4() -> resize_4x4()
* - Euler.to_quat() -> to_quaternion()
* - Matrix.to_quat() -> to_quaternion()
* resizing nolonger returns the resized value.
* - Vector.resize2D -> resize_2d
* - Vector.resize3D -> resize_3d
* - Vector.resize4D -> resize_4d
* added new functions.
* - Vector.to_2d()
* - Vector.to_3d()
* - Vector.to_4d()
* moved into class functions.
* - Mathutils.RotationMatrix -> mathutils.Matrix.Rotation
* - Mathutils.ScaleMatrix -> mathutils.Matrix.Scale
@@ -80,11 +96,12 @@
//-------------------------DOC STRINGS ---------------------------
static char M_Mathutils_doc[] =
"This module provides access to matrices, eulers, quaternions and vectors.";
"This module provides access to matrices, eulers, quaternions and vectors."
;
static int mathutils_array_parse_fast(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
{
PyObject *value_fast= NULL;
PyObject *item;
int i, size;
@@ -106,8 +123,8 @@ static int mathutils_array_parse_fast(float *array, int array_min, int array_max
i= size;
do {
i--;
if(((array[i]= PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i))) == -1.0) && PyErr_Occurred()) {
PyErr_Format(PyExc_ValueError, "%.200s: sequence index %d is not a float", error_prefix, i);
if(((array[i]= PyFloat_AsDouble((item= PySequence_Fast_GET_ITEM(value_fast, i)))) == -1.0) && PyErr_Occurred()) {
PyErr_Format(PyExc_ValueError, "%.200s: sequence index %d expected a number, found '%.200s' type, ", error_prefix, i, Py_TYPE(item)->tp_name);
Py_DECREF(value_fast);
return -1;
}
@@ -148,6 +165,49 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
}
}
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
{
if(EulerObject_Check(value)) {
if(!BaseMath_ReadCallback((BaseMathObject *)value)) {
return -1;
}
else {
eulO_to_mat3(rmat, ((EulerObject *)value)->eul, ((EulerObject *)value)->order);
return 0;
}
}
else if (QuaternionObject_Check(value)) {
if(!BaseMath_ReadCallback((BaseMathObject *)value)) {
return -1;
}
else {
float tquat[4];
normalize_qt_qt(tquat, ((QuaternionObject *)value)->quat);
quat_to_mat3(rmat, tquat);
return 0;
}
}
else if (MatrixObject_Check(value)) {
if(!BaseMath_ReadCallback((BaseMathObject *)value)) {
return -1;
}
else if(((MatrixObject *)value)->colSize < 3 || ((MatrixObject *)value)->rowSize < 3) {
PyErr_Format(PyExc_ValueError, "%.200s: matrix must have minimum 3x3 dimensions", error_prefix);
return -1;
}
else {
matrix_as_3x3(rmat, (MatrixObject *)value);
normalize_m3(rmat);
return 0;
}
}
else {
PyErr_Format(PyExc_TypeError, "%.200s: expected a Euler, Quaternion or Matrix type, found %.200s", error_prefix, Py_TYPE(value)->tp_name);
return -1;
}
}
//----------------------------------MATRIX FUNCTIONS--------------------

View File

@@ -100,5 +100,6 @@ int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index);
/* utility func */
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix);
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix);
#endif /* MATHUTILS_H */

View File

@@ -88,8 +88,8 @@ static char Color_copy_doc[] =
" :return: A copy of the color.\n"
" :rtype: :class:`Color`\n"
"\n"
" .. note:: use this to get a copy of a wrapped color with no reference to the original data.\n";
" .. note:: use this to get a copy of a wrapped color with no reference to the original data.\n"
;
static PyObject *Color_copy(ColorObject *self)
{
if(!BaseMath_ReadCallback(self))
@@ -118,48 +118,40 @@ static PyObject *Color_repr(ColorObject * self)
//------------------------tp_richcmpr
//returns -1 execption, 0 false, 1 true
static PyObject* Color_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
static PyObject* Color_richcmpr(PyObject *a, PyObject *b, int op)
{
ColorObject *colA = NULL, *colB = NULL;
int result = 0;
PyObject *res;
int ok= -1; /* zero is true */
if(ColorObject_Check(objectA)) {
colA = (ColorObject*)objectA;
if(!BaseMath_ReadCallback(colA))
return NULL;
}
if(ColorObject_Check(objectB)) {
colB = (ColorObject*)objectB;
if(!BaseMath_ReadCallback(colB))
if (ColorObject_Check(a) && ColorObject_Check(b)) {
ColorObject *colA= (ColorObject*)a;
ColorObject *colB= (ColorObject*)b;
if(!BaseMath_ReadCallback(colA) || !BaseMath_ReadCallback(colB))
return NULL;
ok= EXPP_VectorsAreEqual(colA->col, colB->col, COLOR_SIZE, 1) ? 0 : -1;
}
if (!colA || !colB){
if (comparison_type == Py_NE){
Py_RETURN_TRUE;
}else{
Py_RETURN_FALSE;
}
}
colA = (ColorObject*)objectA;
colB = (ColorObject*)objectB;
switch (op) {
case Py_NE:
ok = !ok; /* pass through */
case Py_EQ:
res = ok ? Py_False : Py_True;
break;
switch (comparison_type){
case Py_EQ:
result = EXPP_VectorsAreEqual(colA->col, colB->col, COLOR_SIZE, 1);
break;
case Py_NE:
result = !EXPP_VectorsAreEqual(colA->col, colB->col, COLOR_SIZE, 1);
break;
default:
printf("The result of the comparison could not be evaluated");
break;
}
if (result == 1){
Py_RETURN_TRUE;
}else{
Py_RETURN_FALSE;
case Py_LT:
case Py_LE:
case Py_GT:
case Py_GE:
res = Py_NotImplemented;
break;
default:
PyErr_BadArgument();
return NULL;
}
return Py_INCREF(res), res;
}
//---------------------SEQUENCE PROTOCOLS------------------------
@@ -280,7 +272,7 @@ static PyObject *Color_subscript(ColorObject *self, PyObject *item)
return NULL;
if (slicelength <= 0) {
return PyList_New(0);
return PyTuple_New(0);
}
else if (step == 1) {
return Color_slice(self, start, stop);
@@ -461,8 +453,8 @@ static struct PyMethodDef Color_methods[] = {
//------------------PY_OBECT DEFINITION--------------------------
static char color_doc[] =
"This object gives access to Colors in Blender.";
"This object gives access to Colors in Blender."
;
PyTypeObject color_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"mathutils.Color", //tp_name

View File

@@ -20,7 +20,7 @@
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
*
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
@@ -44,7 +44,7 @@
static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *seq= NULL;
char *order_str= NULL;
const char *order_str= NULL;
float eul[EULER_SIZE]= {0.0f, 0.0f, 0.0f};
short order= EULER_ORDER_XYZ;
@@ -72,6 +72,13 @@ static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return newEulerObject(eul, order, Py_NEW, type);
}
/* internal use, assuem read callback is done */
static const char *euler_order_str(EulerObject *self)
{
static const char order[][4] = {"XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"};
return order[self->order-EULER_ORDER_XYZ];
}
short euler_order_from_string(const char *str, const char *error_prefix)
{
if((str[0] && str[1] && str[2] && str[3]=='\0')) {
@@ -114,67 +121,59 @@ static PyObject *Euler_ToTupleExt(EulerObject *self, int ndigits)
//-----------------------------METHODS----------------------------
//return a quaternion representation of the euler
static char Euler_ToQuat_doc[] =
".. method:: to_quat()\n"
static char Euler_to_quaternion_doc[] =
".. method:: to_quaternion()\n"
"\n"
" Return a quaternion representation of the euler.\n"
"\n"
" :return: Quaternion representation of the euler.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Euler_ToQuat(EulerObject * self)
" :rtype: :class:`Quaternion`\n"
;
static PyObject *Euler_to_quaternion(EulerObject * self)
{
float quat[4];
if(!BaseMath_ReadCallback(self))
return NULL;
if(self->order==EULER_ORDER_XYZ) eul_to_quat(quat, self->eul);
else eulO_to_quat(quat, self->eul, self->order);
eulO_to_quat(quat, self->eul, self->order);
return newQuaternionObject(quat, Py_NEW, NULL);
}
//return a matrix representation of the euler
static char Euler_ToMatrix_doc[] =
static char Euler_to_matrix_doc[] =
".. method:: to_matrix()\n"
"\n"
" Return a matrix representation of the euler.\n"
"\n"
" :return: A 3x3 roation matrix representation of the euler.\n"
" :rtype: :class:`Matrix`\n";
static PyObject *Euler_ToMatrix(EulerObject * self)
" :rtype: :class:`Matrix`\n"
;
static PyObject *Euler_to_matrix(EulerObject * self)
{
float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
float mat[9];
if(!BaseMath_ReadCallback(self))
return NULL;
if(self->order==EULER_ORDER_XYZ) eul_to_mat3((float (*)[3])mat, self->eul);
else eulO_to_mat3((float (*)[3])mat, self->eul, self->order);
eulO_to_mat3((float (*)[3])mat, self->eul, self->order);
return newMatrixObject(mat, 3, 3 , Py_NEW, NULL);
}
//sets the euler to 0,0,0
static char Euler_Zero_doc[] =
static char Euler_zero_doc[] =
".. method:: zero()\n"
"\n"
" Set all values to zero.\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Euler`\n";
static PyObject *Euler_Zero(EulerObject * self)
;
static PyObject *Euler_zero(EulerObject * self)
{
self->eul[0] = 0.0;
self->eul[1] = 0.0;
self->eul[2] = 0.0;
zero_v3(self->eul);
(void)BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
Py_RETURN_NONE;
}
static char Euler_rotate_axis_doc[] =
@@ -186,13 +185,11 @@ static char Euler_rotate_axis_doc[] =
" :type axis: string\n"
" :arg angle: angle in radians.\n"
" :type angle: float\n"
" :return: an instance of itself\n"
" :rtype: :class:`Euler`";
;
static PyObject *Euler_rotate_axis(EulerObject * self, PyObject *args)
{
float angle = 0.0f;
char *axis;
const char *axis;
if(!PyArg_ParseTuple(args, "sf:rotate", &axis, &angle)){
PyErr_SetString(PyExc_TypeError, "euler.rotate(): expected angle (float) and axis (x,y,z)");
@@ -206,46 +203,66 @@ static PyObject *Euler_rotate_axis(EulerObject * self, PyObject *args)
if(!BaseMath_ReadCallback(self))
return NULL;
if(self->order == EULER_ORDER_XYZ) rotate_eul(self->eul, *axis, angle);
else rotate_eulO(self->eul, self->order, *axis, angle);
rotate_eulO(self->eul, self->order, *axis, angle);
(void)BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
Py_RETURN_NONE;
}
static char Euler_MakeCompatible_doc[] =
static char Euler_rotate_doc[] =
".. method:: rotate(other)\n"
"\n"
" Rotates the euler a by another mathutils value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
;
static PyObject *Euler_rotate(EulerObject * self, PyObject *value)
{
float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
if(!BaseMath_ReadCallback(self))
return NULL;
if(mathutils_any_to_rotmat(other_rmat, value, "euler.rotate(value)") == -1)
return NULL;
eulO_to_mat3(self_rmat, self->eul, self->order);
mul_m3_m3m3(rmat, self_rmat, other_rmat);
mat3_to_compatible_eulO(self->eul, self->eul, self->order, rmat);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
static char Euler_make_compatible_doc[] =
".. method:: make_compatible(other)\n"
"\n"
" Make this euler compatible with another, so interpolating between them works as intended.\n"
"\n"
" :arg other: make compatible with this rotation.\n"
" :type other: :class:`Euler`\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Euler`\n"
"\n"
" .. note:: the order of eulers must match or an exception is raised.\n";
static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
" .. note:: the rotation order is not taken into account for this function.\n"
;
static PyObject *Euler_make_compatible(EulerObject * self, PyObject *value)
{
if(!EulerObject_Check(value)) {
PyErr_SetString(PyExc_TypeError, "euler.make_compatible(euler): expected a single euler argument");
return NULL;
}
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
float teul[EULER_SIZE];
if(!BaseMath_ReadCallback(self))
return NULL;
if(self->order != value->order) {
PyErr_SetString(PyExc_ValueError, "euler.make_compatible(euler): rotation orders don't match");
if(mathutils_array_parse(teul, EULER_SIZE, EULER_SIZE, value, "euler.make_compatible(other), invalid 'other' arg") == -1)
return NULL;
}
compatible_eul(self->eul, value->eul);
compatible_eul(self->eul, teul);
(void)BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
Py_RETURN_NONE;
}
//----------------------------Euler.rotate()-----------------------
@@ -259,8 +276,8 @@ static char Euler_copy_doc[] =
" :return: A copy of the euler.\n"
" :rtype: :class:`Euler`\n"
"\n"
" .. note:: use this to get a copy of a wrapped euler with no reference to the original data.\n";
" .. note:: use this to get a copy of a wrapped euler with no reference to the original data.\n"
;
static PyObject *Euler_copy(EulerObject *self)
{
if(!BaseMath_ReadCallback(self))
@@ -275,62 +292,52 @@ static PyObject *Euler_copy(EulerObject *self)
static PyObject *Euler_repr(EulerObject * self)
{
PyObject *ret, *tuple;
if(!BaseMath_ReadCallback(self))
return NULL;
tuple= Euler_ToTupleExt(self, -1);
ret= PyUnicode_FromFormat("Euler(%R)", tuple);
ret= PyUnicode_FromFormat("Euler(%R, '%s')", tuple, euler_order_str(self));
Py_DECREF(tuple);
return ret;
}
//------------------------tp_richcmpr
//returns -1 execption, 0 false, 1 true
static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
static PyObject* Euler_richcmpr(PyObject *a, PyObject *b, int op)
{
EulerObject *eulA = NULL, *eulB = NULL;
int result = 0;
PyObject *res;
int ok= -1; /* zero is true */
if(EulerObject_Check(objectA)) {
eulA = (EulerObject*)objectA;
if(!BaseMath_ReadCallback(eulA))
return NULL;
}
if(EulerObject_Check(objectB)) {
eulB = (EulerObject*)objectB;
if(!BaseMath_ReadCallback(eulB))
if (EulerObject_Check(a) && EulerObject_Check(b)) {
EulerObject *eulA= (EulerObject*)a;
EulerObject *eulB= (EulerObject*)b;
if(!BaseMath_ReadCallback(eulA) || !BaseMath_ReadCallback(eulB))
return NULL;
ok= ((eulA->order == eulB->order) && EXPP_VectorsAreEqual(eulA->eul, eulB->eul, EULER_SIZE, 1)) ? 0 : -1;
}
if (!eulA || !eulB){
if (comparison_type == Py_NE){
Py_RETURN_TRUE;
}else{
Py_RETURN_FALSE;
}
}
eulA = (EulerObject*)objectA;
eulB = (EulerObject*)objectB;
switch (op) {
case Py_NE:
ok = !ok; /* pass through */
case Py_EQ:
res = ok ? Py_False : Py_True;
break;
switch (comparison_type){
case Py_EQ:
result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, EULER_SIZE, 1);
break;
case Py_NE:
result = !EXPP_VectorsAreEqual(eulA->eul, eulB->eul, EULER_SIZE, 1);
break;
default:
printf("The result of the comparison could not be evaluated");
break;
}
if (result == 1){
Py_RETURN_TRUE;
}else{
Py_RETURN_FALSE;
case Py_LT:
case Py_LE:
case Py_GT:
case Py_GE:
res = Py_NotImplemented;
break;
default:
PyErr_BadArgument();
return NULL;
}
return Py_INCREF(res), res;
}
//---------------------SEQUENCE PROTOCOLS------------------------
@@ -345,7 +352,7 @@ static int Euler_len(EulerObject *UNUSED(self))
static PyObject *Euler_item(EulerObject * self, int i)
{
if(i<0) i= EULER_SIZE-i;
if(i < 0 || i >= EULER_SIZE) {
PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range");
return NULL;
@@ -369,12 +376,12 @@ static int Euler_ass_item(EulerObject * self, int i, PyObject *value)
}
if(i<0) i= EULER_SIZE-i;
if(i < 0 || i >= EULER_SIZE){
PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range");
return -1;
}
self->eul[i] = f;
if(!BaseMath_WriteIndexCallback(self, i))
@@ -451,7 +458,7 @@ static PyObject *Euler_subscript(EulerObject *self, PyObject *item)
return NULL;
if (slicelength <= 0) {
return PyList_New(0);
return PyTuple_New(0);
}
else if (step == 1) {
return Euler_slice(self, start, stop);
@@ -533,17 +540,15 @@ static int Euler_setAxis(EulerObject *self, PyObject *value, void *type)
/* rotation order */
static PyObject *Euler_getOrder(EulerObject *self, void *UNUSED(closure))
{
const char order[][4] = {"XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"};
if(!BaseMath_ReadCallback(self)) /* can read order too */
return NULL;
return PyUnicode_FromString(order[self->order-EULER_ORDER_XYZ]);
return PyUnicode_FromString(euler_order_str(self));
}
static int Euler_setOrder(EulerObject *self, PyObject *value, void *UNUSED(closure))
{
char *order_str= _PyUnicode_AsString(value);
const char *order_str= _PyUnicode_AsString(value);
short order= euler_order_from_string(order_str, "euler.order");
if(order == -1)
@@ -571,11 +576,12 @@ static PyGetSetDef Euler_getseters[] = {
//-----------------------METHOD DEFINITIONS ----------------------
static struct PyMethodDef Euler_methods[] = {
{"zero", (PyCFunction) Euler_Zero, METH_NOARGS, Euler_Zero_doc},
{"to_matrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, Euler_ToMatrix_doc},
{"to_quat", (PyCFunction) Euler_ToQuat, METH_NOARGS, Euler_ToQuat_doc},
{"zero", (PyCFunction) Euler_zero, METH_NOARGS, Euler_zero_doc},
{"to_matrix", (PyCFunction) Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc},
{"to_quaternion", (PyCFunction) Euler_to_quaternion, METH_NOARGS, Euler_to_quaternion_doc},
{"rotate_axis", (PyCFunction) Euler_rotate_axis, METH_VARARGS, Euler_rotate_axis_doc},
{"make_compatible", (PyCFunction) Euler_MakeCompatible, METH_O, Euler_MakeCompatible_doc},
{"rotate", (PyCFunction) Euler_rotate, METH_O, Euler_rotate_doc},
{"make_compatible", (PyCFunction) Euler_make_compatible, METH_O, Euler_make_compatible_doc},
{"__copy__", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc},
{"copy", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc},
{NULL, NULL, 0, NULL}
@@ -583,8 +589,8 @@ static struct PyMethodDef Euler_methods[] = {
//------------------PY_OBECT DEFINITION--------------------------
static char euler_doc[] =
"This object gives access to Eulers in Blender.";
"This object gives access to Eulers in Blender."
;
PyTypeObject euler_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"mathutils.Euler", //tp_name

File diff suppressed because it is too large Load Diff

View File

@@ -55,4 +55,6 @@ PyObject *newMatrixObject_cb(PyObject *user, int rowSize, int colSize, int cb_ty
extern int mathutils_matrix_vector_cb_index;
extern struct Mathutils_Callback mathutils_matrix_vector_cb;
void matrix_as_3x3(float mat[3][3], MatrixObject *self);
#endif /* MATHUTILS_MATRIX_H */

View File

@@ -20,7 +20,7 @@
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
*
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
@@ -31,14 +31,26 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
#define QUAT_SIZE 4
#define QUAT_APPLY_TO_COPY(quat_meth_noargs, _self) \
QuaternionObject *ret= (QuaternionObject *)Quaternion_copy(_self); \
PyObject *ret_dummy= quat_meth_noargs(ret); \
if(ret_dummy) { \
Py_DECREF(ret_dummy); \
return (PyObject *)ret; \
} \
else { /* error */ \
Py_DECREF(ret); \
return NULL; \
} \
static PyObject *Quaternion_copy(QuaternionObject *self);
//-----------------------------METHODS------------------------------
/* note: BaseMath_ReadCallback must be called beforehand */
static PyObject *Quaternion_ToTupleExt(QuaternionObject *self, int ndigits)
static PyObject *Quaternion_to_tuple_ext(QuaternionObject *self, int ndigits)
{
PyObject *ret;
int i;
@@ -59,7 +71,7 @@ static PyObject *Quaternion_ToTupleExt(QuaternionObject *self, int ndigits)
return ret;
}
static char Quaternion_ToEuler_doc[] =
static char Quaternion_to_euler_doc[] =
".. method:: to_euler(order, euler_compat)\n"
"\n"
" Return Euler representation of the quaternion.\n"
@@ -69,19 +81,19 @@ static char Quaternion_ToEuler_doc[] =
" :arg euler_compat: Optional euler argument the new euler will be made compatible with (no axis flipping between them). Useful for converting a series of matrices to animation curves.\n"
" :type euler_compat: :class:`Euler`\n"
" :return: Euler representation of the quaternion.\n"
" :rtype: :class:`Euler`\n";
static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
" :rtype: :class:`Euler`\n"
;
static PyObject *Quaternion_to_euler(QuaternionObject *self, PyObject *args)
{
float tquat[4];
float eul[3];
char *order_str= NULL;
const char *order_str= NULL;
short order= EULER_ORDER_XYZ;
EulerObject *eul_compat = NULL;
if(!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat))
return NULL;
if(!BaseMath_ReadCallback(self))
return NULL;
@@ -91,15 +103,15 @@ static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
if(order == -1)
return NULL;
}
normalize_qt_qt(tquat, self->quat);
if(eul_compat) {
float mat[3][3];
if(!BaseMath_ReadCallback(eul_compat))
return NULL;
quat_to_mat3(mat, tquat);
if(order == EULER_ORDER_XYZ) mat3_to_compatible_eul(eul, eul_compat->eul, mat);
@@ -109,19 +121,19 @@ static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
if(order == EULER_ORDER_XYZ) quat_to_eul(eul, tquat);
else quat_to_eulO(eul, order, tquat);
}
return newEulerObject(eul, order, Py_NEW, NULL);
}
//----------------------------Quaternion.toMatrix()------------------
static char Quaternion_ToMatrix_doc[] =
static char Quaternion_to_matrix_doc[] =
".. method:: to_matrix()\n"
"\n"
" Return a matrix representation of the quaternion.\n"
"\n"
" :return: A 3x3 rotation matrix representation of the quaternion.\n"
" :rtype: :class:`Matrix`\n";
static PyObject *Quaternion_ToMatrix(QuaternionObject * self)
" :rtype: :class:`Matrix`\n"
;
static PyObject *Quaternion_to_matrix(QuaternionObject *self)
{
float mat[9]; /* all values are set */
@@ -133,7 +145,7 @@ static PyObject *Quaternion_ToMatrix(QuaternionObject * self)
}
//----------------------------Quaternion.cross(other)------------------
static char Quaternion_Cross_doc[] =
static char Quaternion_cross_doc[] =
".. method:: cross(other)\n"
"\n"
" Return the cross product of this quaternion and another.\n"
@@ -141,26 +153,24 @@ static char Quaternion_Cross_doc[] =
" :arg other: The other quaternion to perform the cross product with.\n"
" :type other: :class:`Quaternion`\n"
" :return: The cross product.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Cross(QuaternionObject *self, QuaternionObject *value)
" :rtype: :class:`Quaternion`\n"
;
static PyObject *Quaternion_cross(QuaternionObject *self, PyObject *value)
{
float quat[QUAT_SIZE];
if (!QuaternionObject_Check(value)) {
PyErr_Format(PyExc_TypeError, "quat.cross(value): expected a quaternion argument, not %.200s", Py_TYPE(value)->tp_name);
return NULL;
}
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
float quat[QUAT_SIZE], tquat[QUAT_SIZE];
if(!BaseMath_ReadCallback(self))
return NULL;
mul_qt_qtqt(quat, self->quat, value->quat);
if(mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "quaternion.cross(other), invalid 'other' arg") == -1)
return NULL;
mul_qt_qtqt(quat, self->quat, tquat);
return newQuaternionObject(quat, Py_NEW, Py_TYPE(self));
}
//----------------------------Quaternion.dot(other)------------------
static char Quaternion_Dot_doc[] =
static char Quaternion_dot_doc[] =
".. method:: dot(other)\n"
"\n"
" Return the dot product of this quaternion and another.\n"
@@ -168,22 +178,22 @@ static char Quaternion_Dot_doc[] =
" :arg other: The other quaternion to perform the dot product with.\n"
" :type other: :class:`Quaternion`\n"
" :return: The dot product.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
" :rtype: :class:`Quaternion`\n"
;
static PyObject *Quaternion_dot(QuaternionObject *self, PyObject *value)
{
if (!QuaternionObject_Check(value)) {
PyErr_Format(PyExc_TypeError, "quat.dot(value): expected a quaternion argument, not %.200s", Py_TYPE(value)->tp_name);
return NULL;
}
float tquat[QUAT_SIZE];
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
if(!BaseMath_ReadCallback(self))
return NULL;
return PyFloat_FromDouble(dot_qtqt(self->quat, value->quat));
if(mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "quaternion.dot(other), invalid 'other' arg") == -1)
return NULL;
return PyFloat_FromDouble(dot_qtqt(self->quat, tquat));
}
static char Quaternion_Difference_doc[] =
static char Quaternion_difference_doc[] =
".. function:: difference(other)\n"
"\n"
" Returns a quaternion representing the rotational difference.\n"
@@ -191,26 +201,24 @@ static char Quaternion_Difference_doc[] =
" :arg other: second quaternion.\n"
" :type other: :class:`Quaternion`\n"
" :return: the rotational difference between the two quat rotations.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Difference(QuaternionObject * self, QuaternionObject * value)
" :rtype: :class:`Quaternion`\n"
;
static PyObject *Quaternion_difference(QuaternionObject *self, PyObject *value)
{
float quat[QUAT_SIZE];
float tquat[QUAT_SIZE], quat[QUAT_SIZE];
if (!QuaternionObject_Check(value)) {
PyErr_Format(PyExc_TypeError, "quat.difference(value): expected a quaternion argument, not %.200s", Py_TYPE(value)->tp_name);
return NULL;
}
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
if(!BaseMath_ReadCallback(self))
return NULL;
rotation_between_quats_to_quat(quat, self->quat, value->quat);
if(mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "quaternion.difference(other), invalid 'other' arg") == -1)
return NULL;
rotation_between_quats_to_quat(quat, self->quat, tquat);
return newQuaternionObject(quat, Py_NEW, Py_TYPE(self));
}
static char Quaternion_Slerp_doc[] =
static char Quaternion_slerp_doc[] =
".. function:: slerp(other, factor)\n"
"\n"
" Returns the interpolation of two quaternions.\n"
@@ -220,19 +228,22 @@ static char Quaternion_Slerp_doc[] =
" :arg factor: The interpolation value in [0.0, 1.0].\n"
" :type factor: float\n"
" :return: The interpolated rotation.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Slerp(QuaternionObject *self, PyObject *args)
" :rtype: :class:`Quaternion`\n"
;
static PyObject *Quaternion_slerp(QuaternionObject *self, PyObject *args)
{
QuaternionObject *value;
float quat[QUAT_SIZE], fac;
PyObject *value;
float tquat[QUAT_SIZE], quat[QUAT_SIZE], fac;
if(!PyArg_ParseTuple(args, "O!f:slerp", &quaternion_Type, &value, &fac)) {
if(!PyArg_ParseTuple(args, "Of:slerp", &value, &fac)) {
PyErr_SetString(PyExc_TypeError, "quat.slerp(): expected Quaternion types and float");
return NULL;
}
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
if(!BaseMath_ReadCallback(self))
return NULL;
if(mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "quaternion.slerp(other), invalid 'other' arg") == -1)
return NULL;
if(fac > 1.0f || fac < 0.0f) {
@@ -240,22 +251,49 @@ static PyObject *Quaternion_Slerp(QuaternionObject *self, PyObject *args)
return NULL;
}
interp_qt_qtqt(quat, self->quat, value->quat, fac);
interp_qt_qtqt(quat, self->quat, tquat, fac);
return newQuaternionObject(quat, Py_NEW, Py_TYPE(self));
}
static char Quaternion_rotate_doc[] =
".. method:: rotate(other)\n"
"\n"
" Rotates the quaternion a by another mathutils value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
;
static PyObject *Quaternion_rotate(QuaternionObject *self, PyObject *value)
{
float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
float tquat[4], length;
if(!BaseMath_ReadCallback(self))
return NULL;
if(mathutils_any_to_rotmat(other_rmat, value, "quaternion.rotate(value)") == -1)
return NULL;
length= normalize_qt_qt(tquat, self->quat);
quat_to_mat3(self_rmat, tquat);
mul_m3_m3m3(rmat, self_rmat, other_rmat);
mat3_to_quat(self->quat, rmat);
mul_qt_fl(self->quat, length); /* maintain length after rotating */
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
//----------------------------Quaternion.normalize()----------------
//normalize the axis of rotation of [theta,vector]
static char Quaternion_Normalize_doc[] =
static char Quaternion_normalize_doc[] =
".. function:: normalize()\n"
"\n"
" Normalize the quaternion.\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Normalize(QuaternionObject * self)
;
static PyObject *Quaternion_normalize(QuaternionObject *self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
@@ -263,19 +301,28 @@ static PyObject *Quaternion_Normalize(QuaternionObject * self)
normalize_qt(self->quat);
(void)BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
Py_RETURN_NONE;
}
//----------------------------Quaternion.inverse()------------------
static char Quaternion_Inverse_doc[] =
".. function:: inverse()\n"
static char Quaternion_normalized_doc[] =
".. function:: normalized()\n"
"\n"
" Return a new normalized quaternion.\n"
"\n"
" :return: a normalized copy.\n"
" :rtype: :class:`Quaternion`\n"
;
static PyObject *Quaternion_normalized(QuaternionObject *self)
{
QUAT_APPLY_TO_COPY(Quaternion_normalize, self);
}
//----------------------------Quaternion.invert()------------------
static char Quaternion_invert_doc[] =
".. function:: invert()\n"
"\n"
" Set the quaternion to its inverse.\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Inverse(QuaternionObject * self)
;
static PyObject *Quaternion_invert(QuaternionObject *self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
@@ -283,19 +330,31 @@ static PyObject *Quaternion_Inverse(QuaternionObject * self)
invert_qt(self->quat);
(void)BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
Py_RETURN_NONE;
}
static char Quaternion_inverted_doc[] =
".. function:: inverted()\n"
"\n"
" Return a new, inverted quaternion.\n"
"\n"
" :return: the inverted value.\n"
" :rtype: :class:`Quaternion`\n"
;
static PyObject *Quaternion_inverted(QuaternionObject *self)
{
QUAT_APPLY_TO_COPY(Quaternion_invert, self);
}
//----------------------------Quaternion.identity()-----------------
static char Quaternion_Identity_doc[] =
static char Quaternion_identity_doc[] =
".. function:: identity()\n"
"\n"
" Set the quaternion to an identity quaternion.\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Identity(QuaternionObject * self)
" :rtype: :class:`Quaternion`\n"
;
static PyObject *Quaternion_identity(QuaternionObject *self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
@@ -303,19 +362,18 @@ static PyObject *Quaternion_Identity(QuaternionObject * self)
unit_qt(self->quat);
(void)BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
Py_RETURN_NONE;
}
//----------------------------Quaternion.negate()-------------------
static char Quaternion_Negate_doc[] =
static char Quaternion_negate_doc[] =
".. function:: negate()\n"
"\n"
" Set the quaternion to its negative.\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Negate(QuaternionObject * self)
" :rtype: :class:`Quaternion`\n"
;
static PyObject *Quaternion_negate(QuaternionObject *self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
@@ -323,19 +381,15 @@ static PyObject *Quaternion_Negate(QuaternionObject * self)
mul_qt_fl(self->quat, -1.0f);
(void)BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
Py_RETURN_NONE;
}
//----------------------------Quaternion.conjugate()----------------
static char Quaternion_Conjugate_doc[] =
static char Quaternion_conjugate_doc[] =
".. function:: conjugate()\n"
"\n"
" Set the quaternion to its conjugate (negate x, y, z).\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Conjugate(QuaternionObject * self)
;
static PyObject *Quaternion_conjugate(QuaternionObject *self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
@@ -343,9 +397,21 @@ static PyObject *Quaternion_Conjugate(QuaternionObject * self)
conjugate_qt(self->quat);
(void)BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
Py_RETURN_NONE;
}
static char Quaternion_conjugated_doc[] =
".. function:: conjugated()\n"
"\n"
" Return a new conjugated quaternion.\n"
"\n"
" :return: a new quaternion.\n"
" :rtype: :class:`Quaternion`\n"
;
static PyObject *Quaternion_conjugated(QuaternionObject *self)
{
QUAT_APPLY_TO_COPY(Quaternion_conjugate, self);
}
//----------------------------Quaternion.copy()----------------
static char Quaternion_copy_doc[] =
".. function:: copy()\n"
@@ -355,8 +421,8 @@ static char Quaternion_copy_doc[] =
" :return: A copy of the quaternion.\n"
" :rtype: :class:`Quaternion`\n"
"\n"
" .. note:: use this to get a copy of a wrapped quaternion with no reference to the original data.\n";
" .. note:: use this to get a copy of a wrapped quaternion with no reference to the original data.\n"
;
static PyObject *Quaternion_copy(QuaternionObject *self)
{
if(!BaseMath_ReadCallback(self))
@@ -367,14 +433,14 @@ static PyObject *Quaternion_copy(QuaternionObject *self)
//----------------------------print object (internal)--------------
//print the object to screen
static PyObject *Quaternion_repr(QuaternionObject * self)
static PyObject *Quaternion_repr(QuaternionObject *self)
{
PyObject *ret, *tuple;
if(!BaseMath_ReadCallback(self))
return NULL;
tuple= Quaternion_ToTupleExt(self, -1);
tuple= Quaternion_to_tuple_ext(self, -1);
ret= PyUnicode_FromFormat("Quaternion(%R)", tuple);
@@ -382,53 +448,40 @@ static PyObject *Quaternion_repr(QuaternionObject * self)
return ret;
}
//------------------------tp_richcmpr
//returns -1 execption, 0 false, 1 true
static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
static PyObject* Quaternion_richcmpr(PyObject *a, PyObject *b, int op)
{
QuaternionObject *quatA = NULL, *quatB = NULL;
int result = 0;
PyObject *res;
int ok= -1; /* zero is true */
if(QuaternionObject_Check(objectA)) {
quatA = (QuaternionObject*)objectA;
if(!BaseMath_ReadCallback(quatA))
return NULL;
}
if(QuaternionObject_Check(objectB)) {
quatB = (QuaternionObject*)objectB;
if(!BaseMath_ReadCallback(quatB))
if (QuaternionObject_Check(a) && QuaternionObject_Check(b)) {
QuaternionObject *quatA= (QuaternionObject *)a;
QuaternionObject *quatB= (QuaternionObject *)b;
if(!BaseMath_ReadCallback(quatA) || !BaseMath_ReadCallback(quatB))
return NULL;
ok= (EXPP_VectorsAreEqual(quatA->quat, quatB->quat, QUAT_SIZE, 1)) ? 0 : -1;
}
if (!quatA || !quatB){
if (comparison_type == Py_NE){
Py_RETURN_TRUE;
}else{
Py_RETURN_FALSE;
}
switch (op) {
case Py_NE:
ok = !ok; /* pass through */
case Py_EQ:
res = ok ? Py_False : Py_True;
break;
case Py_LT:
case Py_LE:
case Py_GT:
case Py_GE:
res = Py_NotImplemented;
break;
default:
PyErr_BadArgument();
return NULL;
}
switch (comparison_type){
case Py_EQ:
result = EXPP_VectorsAreEqual(quatA->quat, quatB->quat, QUAT_SIZE, 1);
break;
case Py_NE:
result = EXPP_VectorsAreEqual(quatA->quat, quatB->quat, QUAT_SIZE, 1);
if (result == 0){
result = 1;
}else{
result = 0;
}
break;
default:
printf("The result of the comparison could not be evaluated");
break;
}
if (result == 1){
Py_RETURN_TRUE;
}else{
Py_RETURN_FALSE;
}
return Py_INCREF(res), res;
}
//---------------------SEQUENCE PROTOCOLS------------------------
@@ -440,7 +493,7 @@ static int Quaternion_len(QuaternionObject *UNUSED(self))
}
//----------------------------object[]---------------------------
//sequence accessor (get)
static PyObject *Quaternion_item(QuaternionObject * self, int i)
static PyObject *Quaternion_item(QuaternionObject *self, int i)
{
if(i<0) i= QUAT_SIZE-i;
@@ -457,7 +510,7 @@ static PyObject *Quaternion_item(QuaternionObject * self, int i)
}
//----------------------------object[]-------------------------
//sequence accessor (set)
static int Quaternion_ass_item(QuaternionObject * self, int i, PyObject * ob)
static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob)
{
float scalar= (float)PyFloat_AsDouble(ob);
if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
@@ -480,7 +533,7 @@ static int Quaternion_ass_item(QuaternionObject * self, int i, PyObject * ob)
}
//----------------------------object[z:y]------------------------
//sequence slice (get)
static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end)
static PyObject *Quaternion_slice(QuaternionObject *self, int begin, int end)
{
PyObject *tuple;
int count;
@@ -502,7 +555,7 @@ static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end)
}
//----------------------------object[z:y]------------------------
//sequence slice (set)
static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, PyObject * seq)
static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyObject *seq)
{
int i, size;
float quat[QUAT_SIZE];
@@ -517,7 +570,7 @@ static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, PyO
if((size=mathutils_array_parse(quat, 0, QUAT_SIZE, seq, "mathutils.Quaternion[begin:end] = []")) == -1)
return -1;
if(size != (end - begin)){
PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: size mismatch in slice assignment");
return -1;
@@ -549,7 +602,7 @@ static PyObject *Quaternion_subscript(QuaternionObject *self, PyObject *item)
return NULL;
if (slicelength <= 0) {
return PyList_New(0);
return PyTuple_New(0);
}
else if (step == 1) {
return Quaternion_slice(self, start, stop);
@@ -598,7 +651,7 @@ static int Quaternion_ass_subscript(QuaternionObject *self, PyObject *item, PyOb
//------------------------NUMERIC PROTOCOLS----------------------
//------------------------obj + obj------------------------------
//addition
static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
static PyObject *Quaternion_add(PyObject *q1, PyObject *q2)
{
float quat[QUAT_SIZE];
QuaternionObject *quat1 = NULL, *quat2 = NULL;
@@ -609,7 +662,7 @@ static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
}
quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2;
if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
return NULL;
@@ -618,7 +671,7 @@ static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
}
//------------------------obj - obj------------------------------
//subtraction
static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2)
static PyObject *Quaternion_sub(PyObject *q1, PyObject *q2)
{
int x;
float quat[QUAT_SIZE];
@@ -628,10 +681,10 @@ static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2)
PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation");
return NULL;
}
quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2;
if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
return NULL;
@@ -652,7 +705,7 @@ static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar)
//------------------------obj * obj------------------------------
//mulplication
static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
{
float quat[QUAT_SIZE], scalar;
QuaternionObject *quat1 = NULL, *quat2 = NULL;
@@ -748,17 +801,17 @@ static PyNumberMethods Quaternion_NumMethods = {
0, /* nb_index */
};
static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type )
static PyObject *Quaternion_getAxis( QuaternionObject *self, void *type )
{
return Quaternion_item(self, GET_INT_FROM_POINTER(type));
}
static int Quaternion_setAxis( QuaternionObject * self, PyObject * value, void * type )
static int Quaternion_setAxis( QuaternionObject *self, PyObject *value, void *type )
{
return Quaternion_ass_item(self, GET_INT_FROM_POINTER(type), value);
}
static PyObject *Quaternion_getMagnitude(QuaternionObject * self, void *UNUSED(closure))
static PyObject *Quaternion_getMagnitude(QuaternionObject *self, void *UNUSED(closure))
{
if(!BaseMath_ReadCallback(self))
return NULL;
@@ -766,7 +819,7 @@ static PyObject *Quaternion_getMagnitude(QuaternionObject * self, void *UNUSED(c
return PyFloat_FromDouble(sqrt(dot_qtqt(self->quat, self->quat)));
}
static PyObject *Quaternion_getAngle(QuaternionObject * self, void *UNUSED(closure))
static PyObject *Quaternion_getAngle(QuaternionObject *self, void *UNUSED(closure))
{
float tquat[4];
@@ -777,11 +830,11 @@ static PyObject *Quaternion_getAngle(QuaternionObject * self, void *UNUSED(closu
return PyFloat_FromDouble(2.0 * (saacos(tquat[0])));
}
static int Quaternion_setAngle(QuaternionObject * self, PyObject * value, void *UNUSED(closure))
static int Quaternion_setAngle(QuaternionObject *self, PyObject *value, void *UNUSED(closure))
{
float tquat[4];
float len;
float axis[3], angle_dummy;
double angle;
@@ -807,7 +860,7 @@ static int Quaternion_setAngle(QuaternionObject * self, PyObject * value, void *
) {
axis[0] = 1.0f;
}
axis_angle_to_quat(self->quat, axis, angle);
mul_qt_fl(self->quat, len);
@@ -820,7 +873,7 @@ static int Quaternion_setAngle(QuaternionObject * self, PyObject * value, void *
static PyObject *Quaternion_getAxisVec(QuaternionObject *self, void *UNUSED(closure))
{
float tquat[4];
float axis[3];
float angle;
@@ -848,26 +901,17 @@ static int Quaternion_setAxisVec(QuaternionObject *self, PyObject *value, void *
float axis[3];
float angle;
VectorObject *vec;
if(!BaseMath_ReadCallback(self))
return -1;
len= normalize_qt_qt(tquat, self->quat);
quat_to_axis_angle(axis, &angle, tquat);
quat_to_axis_angle(axis, &angle, tquat); /* axis value is unused */
if(!VectorObject_Check(value)) {
PyErr_SetString(PyExc_TypeError, "quaternion.axis = value: expected a 3D Vector");
return -1;
}
vec= (VectorObject *)value;
if(!BaseMath_ReadCallback(vec))
if (mathutils_array_parse(axis, 3, 3, value, "quat.axis = other") == -1)
return -1;
axis_angle_to_quat(self->quat, vec->vec, angle);
axis_angle_to_quat(self->quat, axis, angle);
mul_qt_fl(self->quat, len);
if(!BaseMath_WriteCallback(self))
@@ -887,7 +931,7 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
PyErr_SetString(PyExc_TypeError, "mathutils.Quaternion(): takes no keyword args");
return NULL;
}
if(!PyArg_ParseTuple(args, "|Od:mathutils.Quaternion", &seq, &angle))
return NULL;
@@ -912,17 +956,31 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
//-----------------------METHOD DEFINITIONS ----------------------
static struct PyMethodDef Quaternion_methods[] = {
{"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, Quaternion_Identity_doc},
{"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, Quaternion_Negate_doc},
{"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, Quaternion_Conjugate_doc},
{"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, Quaternion_Inverse_doc},
{"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, Quaternion_Normalize_doc},
{"to_euler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, Quaternion_ToEuler_doc},
{"to_matrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, Quaternion_ToMatrix_doc},
{"cross", (PyCFunction) Quaternion_Cross, METH_O, Quaternion_Cross_doc},
{"dot", (PyCFunction) Quaternion_Dot, METH_O, Quaternion_Dot_doc},
{"difference", (PyCFunction) Quaternion_Difference, METH_O, Quaternion_Difference_doc},
{"slerp", (PyCFunction) Quaternion_Slerp, METH_VARARGS, Quaternion_Slerp_doc},
/* in place only */
{"identity", (PyCFunction) Quaternion_identity, METH_NOARGS, Quaternion_identity_doc},
{"negate", (PyCFunction) Quaternion_negate, METH_NOARGS, Quaternion_negate_doc},
/* operate on original or copy */
{"conjugate", (PyCFunction) Quaternion_conjugate, METH_NOARGS, Quaternion_conjugate_doc},
{"conjugated", (PyCFunction) Quaternion_conjugated, METH_NOARGS, Quaternion_conjugated_doc},
{"invert", (PyCFunction) Quaternion_invert, METH_NOARGS, Quaternion_invert_doc},
{"inverted", (PyCFunction) Quaternion_inverted, METH_NOARGS, Quaternion_inverted_doc},
{"normalize", (PyCFunction) Quaternion_normalize, METH_NOARGS, Quaternion_normalize_doc},
{"normalized", (PyCFunction) Quaternion_normalized, METH_NOARGS, Quaternion_normalized_doc},
/* return converted representation */
{"to_euler", (PyCFunction) Quaternion_to_euler, METH_VARARGS, Quaternion_to_euler_doc},
{"to_matrix", (PyCFunction) Quaternion_to_matrix, METH_NOARGS, Quaternion_to_matrix_doc},
/* operation between 2 or more types */
{"cross", (PyCFunction) Quaternion_cross, METH_O, Quaternion_cross_doc},
{"dot", (PyCFunction) Quaternion_dot, METH_O, Quaternion_dot_doc},
{"difference", (PyCFunction) Quaternion_difference, METH_O, Quaternion_difference_doc},
{"slerp", (PyCFunction) Quaternion_slerp, METH_VARARGS, Quaternion_slerp_doc},
{"rotate", (PyCFunction) Quaternion_rotate, METH_VARARGS, Quaternion_rotate_doc},
{"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
{"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
{NULL, NULL, 0, NULL}
@@ -946,8 +1004,8 @@ static PyGetSetDef Quaternion_getseters[] = {
//------------------PY_OBECT DEFINITION--------------------------
static char quaternion_doc[] =
"This object gives access to Quaternions in Blender.";
"This object gives access to Quaternions in Blender."
;
PyTypeObject quaternion_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"mathutils.Quaternion", //tp_name
@@ -1005,7 +1063,7 @@ PyTypeObject quaternion_Type = {
PyObject *newQuaternionObject(float *quat, int type, PyTypeObject *base_type)
{
QuaternionObject *self;
if(base_type) self = (QuaternionObject *)base_type->tp_alloc(base_type, 0);
else self = PyObject_NEW(QuaternionObject, &quaternion_Type);

File diff suppressed because it is too large Load Diff

View File

@@ -228,6 +228,10 @@ const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
* chars since blender doesnt limit this */
return result;
}
else if(PyBytes_Check(py_str)) {
PyErr_Clear();
return PyBytes_AS_STRING(py_str);
}
else {
/* mostly copied from fileio.c's, fileio_init */
PyObject *stringobj;
@@ -278,6 +282,10 @@ PyObject *PyC_UnicodeFromByte(const char *str)
for 'pickle' to work as well as strings like this...
>> foo = 10
>> print(__import__("__main__").foo)
*
* note: this overwrites __main__ which gives problems with nested calles.
* be sure to run PyC_MainModule_Backup & PyC_MainModule_Restore if there is
* any chance that python is in the call stack.
*****************************************************************************/
PyObject *PyC_DefaultNameSpace(const char *filename)
{
@@ -293,6 +301,20 @@ PyObject *PyC_DefaultNameSpace(const char *filename)
return PyModule_GetDict(mod_main);
}
/* restore MUST be called after this */
void PyC_MainModule_Backup(PyObject **main_mod)
{
PyInterpreterState *interp= PyThreadState_GET()->interp;
*main_mod= PyDict_GetItemString(interp->modules, "__main__");
Py_XINCREF(*main_mod); /* dont free */
}
void PyC_MainModule_Restore(PyObject *main_mod)
{
PyInterpreterState *interp= PyThreadState_GET()->interp;
PyDict_SetItemString(interp->modules, "__main__", main_mod);
Py_XDECREF(main_mod);
}
/* Would be nice if python had this built in */
void PyC_RunQuicky(const char *filepath, int n, ...)

View File

@@ -39,4 +39,7 @@ const char * PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce); /* coerce m
/* name namespace function for bpy & bge */
PyObject * PyC_DefaultNameSpace(const char *filename);
void PyC_RunQuicky(const char *filepath, int n, ...);
void PyC_MainModule_Backup(PyObject **main_mod);
void PyC_MainModule_Restore(PyObject *main_mod);
#endif // PY_CAPI_UTILS_H

View File

@@ -313,8 +313,22 @@ void BPY_python_end(void)
}
/* super annoying, undo _PyModule_Clear(), bug [#23871] */
#define PYMODULE_CLEAR_WORKAROUND
#ifdef PYMODULE_CLEAR_WORKAROUND
/* bad!, we should never do this, but currently only safe way I could find to keep namespace.
* from being cleared. - campbell */
typedef struct {
PyObject_HEAD
PyObject *md_dict;
/* ommit other values, we only want the dict. */
} PyModuleObject;
#endif
static int python_script_exec(bContext *C, const char *fn, struct Text *text, struct ReportList *reports)
{
PyObject *main_mod= NULL;
PyObject *py_dict= NULL, *py_result= NULL;
PyGILState_STATE gilstate;
@@ -326,6 +340,8 @@ static int python_script_exec(bContext *C, const char *fn, struct Text *text, st
bpy_context_set(C, &gilstate);
PyC_MainModule_Backup(&main_mod);
if (text) {
char fn_dummy[FILE_MAXDIR];
bpy_text_filename_get(fn_dummy, text);
@@ -389,25 +405,21 @@ static int python_script_exec(bContext *C, const char *fn, struct Text *text, st
Py_DECREF( py_result );
}
/* super annoying, undo _PyModule_Clear() */
#define PYMODULE_CLEAR_WORKAROUND
if(py_dict) {
#ifdef PYMODULE_CLEAR_WORKAROUND
PyObject *py_dict_back= PyDict_Copy(py_dict);
Py_INCREF(py_dict);
#endif
/* normal */
PyDict_SetItemString(PyThreadState_GET()->interp->modules, "__main__", Py_None);
#ifdef PYMODULE_CLEAR_WORKAROUND
PyDict_Clear(py_dict);
PyDict_Update(py_dict, py_dict_back);
Py_DECREF(py_dict);
Py_DECREF(py_dict_back);
PyModuleObject *mmod= (PyModuleObject *)PyDict_GetItemString(PyThreadState_GET()->interp->modules, "__main__");
PyObject *dict_back = mmod->md_dict;
/* freeing the module will clear the namespace,
* gives problems running classes defined in this namespace being used later. */
mmod->md_dict= NULL;
Py_DECREF(dict_back);
#endif
#undef PYMODULE_CLEAR_WORKAROUND
}
PyC_MainModule_Restore(main_mod);
bpy_context_clear(C, &gilstate);
return (py_result != NULL);
@@ -437,6 +449,7 @@ int BPY_button_exec(bContext *C, const char *expr, double *value)
PyGILState_STATE gilstate;
PyObject *py_dict, *mod, *retval;
int error_ret = 0;
PyObject *main_mod= NULL;
if (!value || !expr) return -1;
@@ -446,7 +459,9 @@ int BPY_button_exec(bContext *C, const char *expr, double *value)
}
bpy_context_set(C, &gilstate);
PyC_MainModule_Backup(&main_mod);
py_dict= PyC_DefaultNameSpace("<blender button>");
mod = PyImport_ImportModule("math");
@@ -497,7 +512,7 @@ int BPY_button_exec(bContext *C, const char *expr, double *value)
BPy_errors_to_report(CTX_wm_reports(C));
}
PyDict_SetItemString(PyThreadState_GET()->interp->modules, "__main__", Py_None);
PyC_MainModule_Backup(&main_mod);
bpy_context_clear(C, &gilstate);
@@ -507,6 +522,7 @@ int BPY_button_exec(bContext *C, const char *expr, double *value)
int BPY_string_exec(bContext *C, const char *expr)
{
PyGILState_STATE gilstate;
PyObject *main_mod= NULL;
PyObject *py_dict, *retval;
int error_ret = 0;
@@ -518,6 +534,8 @@ int BPY_string_exec(bContext *C, const char *expr)
bpy_context_set(C, &gilstate);
PyC_MainModule_Backup(&main_mod);
py_dict= PyC_DefaultNameSpace("<blender string>");
retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict);
@@ -531,8 +549,8 @@ int BPY_string_exec(bContext *C, const char *expr)
Py_DECREF(retval);
}
PyDict_SetItemString(PyThreadState_GET()->interp->modules, "__main__", Py_None);
PyC_MainModule_Restore(main_mod);
bpy_context_clear(C, &gilstate);
return error_ret;

View File

@@ -138,6 +138,11 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
return NULL;
}
if(!pyrna_write_check()) {
PyErr_Format(PyExc_SystemError, "Calling operator \"bpy.ops.%s\" error, can't modify blend data in this state (drawing/rendering)", opname);
return NULL;
}
if(context_str) {
if(RNA_enum_value_from_id(operator_context_items, context_str, &context)==0) {
char *enum_str= BPy_enum_as_string(operator_context_items);
@@ -226,6 +231,12 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
return NULL;
}
/* when calling bpy.ops.wm.read_factory_settings() bpy.data's main pointer is freed by clear_globals(),
* further access will crash blender. setting context is not needed in this case, only calling because this
* function corrects bpy.data (internal Main pointer) */
BPY_modules_update(C);
/* return operator_ret as a bpy enum */
return pyrna_enum_bitfield_to_py(operator_return_items, operator_ret);

View File

@@ -83,7 +83,19 @@ static int rna_id_write_error(PointerRNA *ptr, PyObject *key)
}
return FALSE;
}
#endif // USE_PEDANTIC_WRITE
#ifdef USE_PEDANTIC_WRITE
int pyrna_write_check(void)
{
return !rna_disallow_writes;
}
#else // USE_PEDANTIC_WRITE
int pyrna_write_check(void)
{
return TRUE;
}
#endif // USE_PEDANTIC_WRITE
static Py_ssize_t pyrna_prop_collection_length(BPy_PropertyRNA *self);
@@ -423,9 +435,9 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
int pyrna_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value, const char *error_prefix)
{
if(RNA_enum_value_from_id(item, identifier, value) == 0) {
char *enum_str= BPy_enum_as_string(item);
const char *enum_str= BPy_enum_as_string(item);
PyErr_Format(PyExc_TypeError, "%s: '%.200s' not found in (%s)", error_prefix, identifier, enum_str);
MEM_freeN(enum_str);
MEM_freeN((void *)enum_str);
return -1;
}
@@ -504,13 +516,13 @@ static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op)
static PyObject *pyrna_struct_str( BPy_StructRNA *self )
{
PyObject *ret;
char *name;
const char *name;
/* print name if available */
name= RNA_struct_name_get_alloc(&self->ptr, NULL, FALSE);
if(name) {
ret= PyUnicode_FromFormat( "<bpy_struct, %.200s(\"%.200s\")>", RNA_struct_identifier(self->ptr.type), name);
MEM_freeN(name);
MEM_freeN((void *)name);
return ret;
}
@@ -528,11 +540,11 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self)
}
else {
PyObject *ret;
char *path;
const char *path;
path= RNA_path_from_ID_to_struct(&self->ptr);
if(path) {
ret= PyUnicode_FromFormat( "bpy.data.%s[\"%s\"].%s", BKE_idcode_to_name_plural(GS(id->name)), id->name+2, path);
MEM_freeN(path);
MEM_freeN((void *)path);
}
else { /* cant find, print something sane */
ret= PyUnicode_FromFormat( "bpy.data.%s[\"%s\"]...%s", BKE_idcode_to_name_plural(GS(id->name)), id->name+2, RNA_struct_identifier(self->ptr.type));
@@ -546,7 +558,7 @@ static PyObject *pyrna_prop_str( BPy_PropertyRNA *self )
{
PyObject *ret;
PointerRNA ptr;
char *name;
const char *name;
const char *type_id= NULL;
char type_fmt[64]= "";
int type= RNA_property_type(self->prop);
@@ -579,7 +591,7 @@ static PyObject *pyrna_prop_str( BPy_PropertyRNA *self )
if(name) {
ret= PyUnicode_FromFormat( "<bpy_%.200s, %.200s.%.200s(\"%.200s\")>", type_fmt, RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop), name);
MEM_freeN(name);
MEM_freeN((void *)name);
return ret;
}
}
@@ -591,7 +603,7 @@ static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self)
{
ID *id= self->ptr.id.data;
PyObject *ret;
char *path;
const char *path;
if(id == NULL)
return pyrna_prop_str(self); /* fallback */
@@ -599,7 +611,7 @@ static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self)
path= RNA_path_from_ID_to_property(&self->ptr, self->prop);
if(path) {
ret= PyUnicode_FromFormat( "bpy.data.%s[\"%s\"].%s", BKE_idcode_to_name_plural(GS(id->name)), id->name+2, path);
MEM_freeN(path);
MEM_freeN((void *)path);
}
else { /* cant find, print something sane */
ret= PyUnicode_FromFormat( "bpy.data.%s[\"%s\"]...%s", BKE_idcode_to_name_plural(GS(id->name)), id->name+2, RNA_property_identifier(self->prop));
@@ -670,7 +682,7 @@ static const char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop)
static int pyrna_string_to_enum(PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *val, const char *error_prefix)
{
char *param= _PyUnicode_AsString(item);
const char *param= _PyUnicode_AsString(item);
if (param==NULL) {
const char *enum_str= pyrna_enum_as_string(ptr, prop);
@@ -702,7 +714,7 @@ int pyrna_set_to_enum_bitfield(EnumPropertyItem *items, PyObject *value, int *r_
*r_value= 0;
while (_PySet_NextEntry(value, &pos, &key, &hash)) {
char *param= _PyUnicode_AsString(key);
const char *param= _PyUnicode_AsString(key);
if(param==NULL) {
PyErr_Format(PyExc_TypeError, "%.200s expected a string. found a %.200s", error_prefix, Py_TYPE(key)->tp_name);
@@ -800,7 +812,7 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
ret= PyUnicode_FromString(item->identifier);
}
else {
char *ptr_name= RNA_struct_name_get_alloc(ptr, NULL, FALSE);
const char *ptr_name= RNA_struct_name_get_alloc(ptr, NULL, FALSE);
/* prefer not fail silently incase of api errors, maybe disable it later */
printf("RNA Warning: Current value \"%d\" matches no enum in '%s', '%s', '%s'\n", val, RNA_struct_identifier(ptr->type), ptr_name, RNA_property_identifier(prop));
@@ -812,9 +824,9 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
#endif
if(ptr_name)
MEM_freeN(ptr_name);
MEM_freeN((void *)ptr_name);
ret = PyUnicode_FromString( "" );
ret = PyUnicode_FromString("");
}
if(free)
@@ -851,7 +863,7 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
case PROP_STRING:
{
int subtype= RNA_property_subtype(prop);
char *buf;
const char *buf;
buf = RNA_property_string_get_alloc(ptr, prop, NULL, -1);
#ifdef USE_STRING_COERCE
/* only file paths get special treatment, they may contain non utf-8 chars */
@@ -864,7 +876,7 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
#else // USE_STRING_COERCE
ret= PyUnicode_FromString(buf);
#endif // USE_STRING_COERCE
MEM_freeN(buf);
MEM_freeN((void *)buf);
break;
}
case PROP_ENUM:
@@ -1277,7 +1289,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
if(pyrna_pydict_to_props(&itemptr, item, 1, "Converting a python list to an RNA collection")==-1) {
PyObject *msg= PyC_ExceptionBuffer();
char *msg_char= _PyUnicode_AsString(msg);
const char *msg_char= _PyUnicode_AsString(msg);
PyErr_Format(PyExc_TypeError, "%.200s %.200s.%.200s error converting a member of a collection from a dicts into an RNA collection, failed with: %s", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), msg_char);
@@ -1899,7 +1911,7 @@ static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *value
PointerRNA newptr; /* not used, just so RNA_property_collection_lookup_string runs */
/* key in dict style check */
char *keyname = _PyUnicode_AsString(value);
const char *keyname = _PyUnicode_AsString(value);
if(keyname==NULL) {
PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.__contains__: expected a string");
@@ -1915,7 +1927,7 @@ static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *value
static int pyrna_struct_contains(BPy_StructRNA *self, PyObject *value)
{
IDProperty *group;
char *name = _PyUnicode_AsString(value);
const char *name = _PyUnicode_AsString(value);
if (!name) {
PyErr_SetString(PyExc_TypeError, "bpy_struct.__contains__: expected a string");
@@ -1978,7 +1990,7 @@ static PyObject *pyrna_struct_subscript( BPy_StructRNA *self, PyObject *key )
{
/* mostly copied from BPy_IDGroup_Map_GetItem */
IDProperty *group, *idprop;
char *name= _PyUnicode_AsString(key);
const char *name= _PyUnicode_AsString(key);
if(RNA_struct_idprops_check(self->ptr.type)==0) {
PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties");
@@ -2114,7 +2126,7 @@ static PyObject *pyrna_struct_values(BPy_PropertyRNA *self)
/* for keyframes and drivers */
static int pyrna_struct_anim_args_parse(PointerRNA *ptr, const char *error_prefix, const char *path,
char **path_full, int *index)
const char **path_full, int *index)
{
const int is_idbase= RNA_struct_is_ID(ptr->type);
PropertyRNA *prop;
@@ -2189,10 +2201,10 @@ static int pyrna_struct_anim_args_parse(PointerRNA *ptr, const char *error_prefi
/* internal use for insert and delete */
static int pyrna_struct_keyframe_parse(PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix,
char **path_full, int *index, float *cfra, char **group_name) /* return values */
const char **path_full, int *index, float *cfra, const char **group_name) /* return values */
{
static const char *kwlist[] = {"data_path", "index", "frame", "group", NULL};
char *path;
const char *path;
/* note, parse_str MUST start with 's|ifs' */
if (!PyArg_ParseTupleAndKeywords(args, kw, parse_str, (char **)kwlist, &path, index, cfra, group_name))
@@ -2226,10 +2238,10 @@ static char pyrna_struct_keyframe_insert_doc[] =
static PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyObject *kw)
{
/* args, pyrna_struct_keyframe_parse handles these */
char *path_full= NULL;
const char *path_full= NULL;
int index= -1;
float cfra= FLT_MAX;
char *group_name= NULL;
const char *group_name= NULL;
if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()", &path_full, &index, &cfra, &group_name) == -1) {
return NULL;
@@ -2241,7 +2253,7 @@ static PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *arg
BKE_reports_init(&reports, RPT_STORE);
result= insert_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0);
MEM_freeN(path_full);
MEM_freeN((void *)path_full);
if(BPy_reports_to_error(&reports, TRUE))
return NULL;
@@ -2269,10 +2281,10 @@ static char pyrna_struct_keyframe_delete_doc[] =
static PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyObject *kw)
{
/* args, pyrna_struct_keyframe_parse handles these */
char *path_full= NULL;
const char *path_full= NULL;
int index= -1;
float cfra= FLT_MAX;
char *group_name= NULL;
const char *group_name= NULL;
if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_delete()", "bpy_struct.keyframe_insert()", &path_full, &index, &cfra, &group_name) == -1) {
return NULL;
@@ -2284,7 +2296,7 @@ static PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *arg
BKE_reports_init(&reports, RPT_STORE);
result= delete_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0);
MEM_freeN(path_full);
MEM_freeN((void *)path_full);
if(BPy_reports_to_error(&reports, TRUE))
return NULL;
@@ -2308,7 +2320,7 @@ static char pyrna_struct_driver_add_doc[] =
static PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
{
char *path, *path_full;
const char *path, *path_full;
int index= -1;
if (!PyArg_ParseTuple(args, "s|i:driver_add", &path, &index))
@@ -2359,7 +2371,7 @@ static PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
return NULL;
}
MEM_freeN(path_full);
MEM_freeN((void *)path_full);
return ret;
}
@@ -2380,7 +2392,7 @@ static char pyrna_struct_driver_remove_doc[] =
static PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args)
{
char *path, *path_full;
const char *path, *path_full;
int index= -1;
if (!PyArg_ParseTuple(args, "s|i:driver_remove", &path, &index))
@@ -2397,7 +2409,7 @@ static PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args)
result= ANIM_remove_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0);
MEM_freeN(path_full);
MEM_freeN((void *)path_full);
if(BPy_reports_to_error(&reports, TRUE))
return NULL;
@@ -2418,7 +2430,7 @@ static char pyrna_struct_is_property_set_doc[] =
static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *args)
{
PropertyRNA *prop;
char *name;
const char *name;
int ret;
if (!PyArg_ParseTuple(args, "s:is_property_set", &name))
@@ -2458,7 +2470,7 @@ static char pyrna_struct_is_property_hidden_doc[] =
static PyObject *pyrna_struct_is_property_hidden(BPy_StructRNA *self, PyObject *args)
{
PropertyRNA *prop;
char *name;
const char *name;
if (!PyArg_ParseTuple(args, "s:is_property_hidden", &name))
return NULL;
@@ -2483,7 +2495,7 @@ static char pyrna_struct_path_resolve_doc[] =
static PyObject *pyrna_struct_path_resolve(BPy_StructRNA *self, PyObject *args)
{
char *path;
const char *path;
PyObject *coerce= Py_True;
PointerRNA r_ptr;
PropertyRNA *r_prop;
@@ -2534,8 +2546,8 @@ static char pyrna_struct_path_from_id_doc[] =
static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args)
{
char *name= NULL;
char *path;
const char *name= NULL;
const char *path;
PropertyRNA *prop;
PyObject *ret;
@@ -2562,7 +2574,7 @@ static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args)
}
ret= PyUnicode_FromString(path);
MEM_freeN(path);
MEM_freeN((void *)path);
return ret;
}
@@ -2577,7 +2589,7 @@ static char pyrna_prop_path_from_id_doc[] =
static PyObject *pyrna_prop_path_from_id(BPy_PropertyRNA *self)
{
char *path;
const char *path;
PropertyRNA *prop = self->prop;
PyObject *ret;
@@ -2589,7 +2601,7 @@ static PyObject *pyrna_prop_path_from_id(BPy_PropertyRNA *self)
}
ret= PyUnicode_FromString(path);
MEM_freeN(path);
MEM_freeN((void *)path);
return ret;
}
@@ -2724,7 +2736,7 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA *self)
//---------------getattr--------------------------------------------
static PyObject *pyrna_struct_getattro( BPy_StructRNA *self, PyObject *pyname )
{
char *name = _PyUnicode_AsString(pyname);
const char *name = _PyUnicode_AsString(pyname);
PyObject *ret;
PropertyRNA *prop;
FunctionRNA *func;
@@ -2902,13 +2914,13 @@ static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyOb
}
else {
/* remove existing property if its set or we also end up with confusement */
char *attr_str= _PyUnicode_AsString(attr);
const char *attr_str= _PyUnicode_AsString(attr);
RNA_def_property_free_identifier(srna, attr_str); /* ignore on failier */
}
}
else { /* __delattr__ */
/* first find if this is a registered property */
char *attr_str= _PyUnicode_AsString(attr);
const char *attr_str= _PyUnicode_AsString(attr);
int ret= RNA_def_property_free_identifier(srna, attr_str);
if (ret == -1) {
PyErr_Format(PyExc_TypeError, "struct_meta_idprop.detattr(): '%s' not a dynamic property", attr_str);
@@ -2922,7 +2934,7 @@ static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyOb
static int pyrna_struct_setattro( BPy_StructRNA *self, PyObject *pyname, PyObject *value )
{
char *name = _PyUnicode_AsString(pyname);
const char *name = _PyUnicode_AsString(pyname);
PropertyRNA *prop= NULL;
#ifdef USE_PEDANTIC_WRITE
@@ -3005,7 +3017,7 @@ static PyObject *pyrna_prop_array_getattro( BPy_PropertyRNA *self, PyObject *pyn
static PyObject *pyrna_prop_collection_getattro( BPy_PropertyRNA *self, PyObject *pyname )
{
char *name = _PyUnicode_AsString(pyname);
const char *name = _PyUnicode_AsString(pyname);
if(name == NULL) {
PyErr_SetString(PyExc_AttributeError, "bpy_prop_collection: __getattr__ must be a string");
@@ -3040,7 +3052,7 @@ static PyObject *pyrna_prop_collection_getattro( BPy_PropertyRNA *self, PyObject
//--------------- setattr-------------------------------------------
static int pyrna_prop_collection_setattro( BPy_PropertyRNA *self, PyObject *pyname, PyObject *value )
{
char *name = _PyUnicode_AsString(pyname);
const char *name = _PyUnicode_AsString(pyname);
PropertyRNA *prop;
PointerRNA r_ptr;
@@ -3225,7 +3237,7 @@ static PyObject *pyrna_struct_get(BPy_StructRNA *self, PyObject *args)
{
IDProperty *group, *idprop;
char *key;
const char *key;
PyObject* def = Py_None;
if (!PyArg_ParseTuple(args, "s|O:get", &key, &def))
@@ -3267,7 +3279,7 @@ static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args
{
PointerRNA newptr;
char *key;
const char *key;
PyObject* def = Py_None;
if (!PyArg_ParseTuple(args, "s|O:get", &key, &def))
@@ -3279,7 +3291,7 @@ static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args
return Py_INCREF(def), def;
}
static void foreach_attr_type( BPy_PropertyRNA *self, char *attr,
static void foreach_attr_type( BPy_PropertyRNA *self, const char *attr,
/* values to assign */
RawPropertyType *raw_type, int *attr_tot, int *attr_signed )
{
@@ -3304,7 +3316,7 @@ static int foreach_parse_args(
BPy_PropertyRNA *self, PyObject *args,
/*values to assign */
char **attr, PyObject **seq, int *tot, int *size, RawPropertyType *raw_type, int *attr_tot, int *attr_signed)
const char **attr, PyObject **seq, int *tot, int *size, RawPropertyType *raw_type, int *attr_tot, int *attr_signed)
{
#if 0
int array_tot;
@@ -3386,7 +3398,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
void *array= NULL;
/* get/set both take the same args currently */
char *attr;
const char *attr;
PyObject *seq;
int tot, size, attr_tot, attr_signed;
RawPropertyType raw_type;
@@ -3986,7 +3998,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
DynStr *bad_args= BLI_dynstr_new();
DynStr *good_args= BLI_dynstr_new();
char *arg_name, *bad_args_str, *good_args_str;
const char *arg_name, *bad_args_str, *good_args_str;
int found= FALSE, first= TRUE;
while (PyDict_Next(kw, &pos, &key, &value)) {
@@ -4039,8 +4051,8 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
BLI_dynstr_free(bad_args);
BLI_dynstr_free(good_args);
MEM_freeN(bad_args_str);
MEM_freeN(good_args_str);
MEM_freeN((void *)bad_args_str);
MEM_freeN((void *)good_args_str);
err= -1;
}
@@ -4868,7 +4880,7 @@ static PyObject *pyrna_basetype_getattro( BPy_BaseTypeRNA *self, PyObject *pynam
{
PointerRNA newptr;
PyObject *ret;
char *name= _PyUnicode_AsString(pyname);
const char *name= _PyUnicode_AsString(pyname);
if(name == NULL) {
PyErr_SetString(PyExc_AttributeError, "bpy.types: __getattr__ must be a string");
@@ -5304,8 +5316,6 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
return 0;
}
extern void BPY_modules_update(bContext *C); //XXX temp solution
/* TODO - multiple return values like with rna functions */
static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms)
{
@@ -5324,8 +5334,9 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
PyGILState_STATE gilstate;
#ifdef USE_PEDANTIC_WRITE
const char *func_id= RNA_function_identifier(func);
/* testing, for correctness, not operator and not draw function */
const short is_readonly= strstr("draw", RNA_function_identifier(func)) || !RNA_struct_is_a(ptr->type, &RNA_Operator);
const short is_readonly= strstr("draw", func_id) || /*strstr("render", func_id) ||*/ !RNA_struct_is_a(ptr->type, &RNA_Operator);
#endif
py_class= RNA_struct_py_type_get(ptr->type);

View File

@@ -108,4 +108,8 @@ PyObject *pyrna_py_from_array_index(BPy_PropertyArrayRNA *self, PointerRNA *ptr,
PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop);
int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value);
int pyrna_write_check(void);
void BPY_modules_update(struct bContext *C); //XXX temp solution
#endif

View File

@@ -18,6 +18,8 @@
#
# #**** END GPL LICENSE BLOCK #****
# <pep8 compliant>
if 1:
# Print once every 1000
GEN_PATH = True
@@ -37,6 +39,7 @@ else:
seek_count = [0]
def seek(r, txt, recurs):
seek_count[0] += 1
@@ -71,52 +74,60 @@ def seek(r, txt, recurs):
print(txt + ' -> "' + str(r) + '"')
return
try: keys = r.keys()
except: keys = None
try:
keys = r.keys()
except:
keys = None
if keys != None:
if PRINT_DATA:
print(txt + '.keys() - ' + str(r.keys()))
try: __members__ = dir(r)
except: __members__ = []
try:
__members__ = dir(r)
except:
__members__ = []
for item in __members__:
if item.startswith('__'):
if item.startswith("__"):
continue
if GEN_PATH: newtxt = txt + '.' + item
if GEN_PATH:
newtxt = txt + '.' + item
if item == 'rna_type' and VERBOSE_TYPE==False: # just avoid because it spits out loads of data
if item == 'rna_type' and VERBOSE_TYPE == False: # just avoid because it spits out loads of data
continue
try: value = getattr(r, item)
except: value = None
seek( value, newtxt, recurs + 1)
value = getattr(r, item, None)
seek(value, newtxt, recurs + 1)
if keys:
for k in keys:
if GEN_PATH: newtxt = txt + '["' + k + '"]'
seek(r.__getitem__(k), newtxt, recurs+1)
if GEN_PATH:
newtxt = txt + '["' + k + '"]'
seek(r.__getitem__(k), newtxt, recurs + 1)
else:
try: length = len( r )
except: length = 0
try:
length = len(r)
except:
length = 0
if VERBOSE==False and length >= 4:
for i in (0, length-1):
if i>0:
if VERBOSE == False and length >= 4:
for i in (0, length - 1):
if i > 0:
if PRINT_DATA:
print((' '*len(txt)) + ' ... skipping '+str(length-2)+' items ...')
print((" " * len(txt)) + " ... skipping " + str(length - 2) + " items ...")
if GEN_PATH: newtxt = txt + '[' + str(i) + ']'
seek(r[i], newtxt, recurs+1)
if GEN_PATH:
newtxt = txt + '[' + str(i) + ']'
seek(r[i], newtxt, recurs + 1)
else:
for i in range(length):
if GEN_PATH: newtxt = txt + '[' + str(i) + ']'
seek(r[i], newtxt, recurs+1)
if GEN_PATH:
newtxt = txt + '[' + str(i) + ']'
seek(r[i], newtxt, recurs + 1)
seek(bpy.data, 'bpy.data', 0)
# seek(bpy.types, 'bpy.types', 0)