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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/python')
-rw-r--r--source/blender/python/SConscript3
-rw-r--r--source/blender/python/doc/sphinx_doc_gen.py4
-rw-r--r--source/blender/python/generic/bpy_internal_import.c23
-rw-r--r--source/blender/python/generic/bpy_internal_import.h2
-rw-r--r--source/blender/python/generic/mathutils.c71
-rw-r--r--source/blender/python/generic/mathutils.h2
-rw-r--r--source/blender/python/generic/mathutils_color.c14
-rw-r--r--source/blender/python/generic/mathutils_euler.c8
-rw-r--r--source/blender/python/generic/mathutils_matrix.c8
-rw-r--r--source/blender/python/generic/mathutils_quat.c28
-rw-r--r--source/blender/python/generic/mathutils_vector.c23
-rw-r--r--source/blender/python/intern/bpy.c2
-rw-r--r--source/blender/python/intern/bpy_interface.c34
-rw-r--r--source/blender/python/intern/bpy_rna.c156
-rw-r--r--source/blender/python/intern/bpy_rna_callback.c29
15 files changed, 207 insertions, 200 deletions
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript
index b4ce9898b1b..c9dc60dcc92 100644
--- a/source/blender/python/SConscript
+++ b/source/blender/python/SConscript
@@ -11,6 +11,9 @@ incs += ' ' + env['BF_PYTHON_INC']
defs = []
+if env['BF_BUILDINFO']:
+ defs.append('BUILD_DATE')
+
if env['OURPLATFORM'] in ('win32-mingw', 'win32-vc','win64-vc') and env['BF_DEBUG']:
defs.append('_DEBUG')
diff --git a/source/blender/python/doc/sphinx_doc_gen.py b/source/blender/python/doc/sphinx_doc_gen.py
index 7e4043c75ca..a74f95a63c4 100644
--- a/source/blender/python/doc/sphinx_doc_gen.py
+++ b/source/blender/python/doc/sphinx_doc_gen.py
@@ -367,6 +367,7 @@ def rna2sphinx(BASEPATH):
# py modules
fw(" bpy.utils.rst\n\n")
+ fw(" bpy.path.rst\n\n")
fw(" bpy.app.rst\n\n")
# C modules
@@ -448,6 +449,9 @@ def rna2sphinx(BASEPATH):
from bpy import utils as module
pymodule2sphinx(BASEPATH, "bpy.utils", module, "Utilities (bpy.utils)")
+ from bpy import path as module
+ pymodule2sphinx(BASEPATH, "bpy.path", module, "Path Utilities (bpy.path)")
+
# C modules
from bpy import app as module
pymodule2sphinx(BASEPATH, "bpy.app", module, "Application Data (bpy.app)")
diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c
index 2e45391247e..0bcecafd23c 100644
--- a/source/blender/python/generic/bpy_internal_import.c
+++ b/source/blender/python/generic/bpy_internal_import.c
@@ -350,3 +350,26 @@ void bpy_text_clear_modules(int clear_all)
Py_DECREF(list); /* removes all references from append */
}
#endif
+
+
+/*****************************************************************************
+* Description: This function creates a new Python dictionary object.
+* note: dict is owned by sys.modules["__main__"] module, reference is borrowed
+* note: important we use the dict from __main__, this is what python expects
+ for 'pickle' to work as well as strings like this...
+ >> foo = 10
+ >> print(__import__("__main__").foo)
+*****************************************************************************/
+PyObject *bpy_namespace_dict_new(const char *filename)
+{
+ PyInterpreterState *interp= PyThreadState_GET()->interp;
+ PyObject *mod_main= PyModule_New("__main__");
+ PyDict_SetItemString(interp->modules, "__main__", mod_main);
+ Py_DECREF(mod_main); /* sys.modules owns now */
+ PyModule_AddStringConstant(mod_main, "__name__", "__main__");
+ if(filename)
+ PyModule_AddStringConstant(mod_main, "__file__", filename); /* __file__ only for nice UI'ness */
+ PyModule_AddObject(mod_main, "__builtins__", interp->builtins);
+ Py_INCREF(interp->builtins); /* AddObject steals a reference */
+ return PyModule_GetDict(mod_main);
+}
diff --git a/source/blender/python/generic/bpy_internal_import.h b/source/blender/python/generic/bpy_internal_import.h
index 37136d46c9e..83e05fd6ded 100644
--- a/source/blender/python/generic/bpy_internal_import.h
+++ b/source/blender/python/generic/bpy_internal_import.h
@@ -60,5 +60,7 @@ extern PyMethodDef bpy_reload_meth[];
struct Main *bpy_import_main_get(void);
void bpy_import_main_set(struct Main *maggie);
+/* name namespace function for bpy & bge */
+PyObject *bpy_namespace_dict_new(const char *filename);
#endif /* EXPP_bpy_import_h */
diff --git a/source/blender/python/generic/mathutils.c b/source/blender/python/generic/mathutils.c
index f953e7c6e4f..2bfd9a6d0c6 100644
--- a/source/blender/python/generic/mathutils.c
+++ b/source/blender/python/generic/mathutils.c
@@ -44,6 +44,7 @@
* - toEuler --> to_euler
* - toQuat --> to_quat
* - Vector.toTrackQuat --> Vector.to_track_quat
+ * - Quaternion * Quaternion --> cross product (not dot product)
*
* Moved to Geometry module: Intersect, TriangleArea, TriangleNormal, QuadNormal, LineIntersect
*/
@@ -92,74 +93,6 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
return size;
}
-//-----------------------------METHODS----------------------------
-//-----------------quat_rotation (internal)-----------
-//This function multiplies a vector/point * quat or vice versa
-//to rotate the point/vector by the quaternion
-//arguments should all be 3D
-PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
-{
- float rot[3];
- QuaternionObject *quat = NULL;
- VectorObject *vec = NULL;
-
- if(QuaternionObject_Check(arg1)){
- quat = (QuaternionObject*)arg1;
- if(!BaseMath_ReadCallback(quat))
- return NULL;
-
- if(VectorObject_Check(arg2)){
- vec = (VectorObject*)arg2;
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
- rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] -
- 2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] +
- 2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] -
- quat->quat[3]*quat->quat[3]*vec->vec[0] - quat->quat[2]*quat->quat[2]*vec->vec[0];
- rot[1] = 2*quat->quat[1]*quat->quat[2]*vec->vec[0] + quat->quat[2]*quat->quat[2]*vec->vec[1] +
- 2*quat->quat[3]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[3]*vec->vec[0] -
- quat->quat[3]*quat->quat[3]*vec->vec[1] + quat->quat[0]*quat->quat[0]*vec->vec[1] -
- 2*quat->quat[1]*quat->quat[0]*vec->vec[2] - quat->quat[1]*quat->quat[1]*vec->vec[1];
- rot[2] = 2*quat->quat[1]*quat->quat[3]*vec->vec[0] + 2*quat->quat[2]*quat->quat[3]*vec->vec[1] +
- quat->quat[3]*quat->quat[3]*vec->vec[2] - 2*quat->quat[0]*quat->quat[2]*vec->vec[0] -
- quat->quat[2]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[1]*vec->vec[1] -
- quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2];
- return newVectorObject(rot, 3, Py_NEW, NULL);
- }
- }else if(VectorObject_Check(arg1)){
- vec = (VectorObject*)arg1;
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
- if(QuaternionObject_Check(arg2)){
- quat = (QuaternionObject*)arg2;
- if(!BaseMath_ReadCallback(quat))
- return NULL;
-
- rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] -
- 2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] +
- 2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] -
- quat->quat[3]*quat->quat[3]*vec->vec[0] - quat->quat[2]*quat->quat[2]*vec->vec[0];
- rot[1] = 2*quat->quat[1]*quat->quat[2]*vec->vec[0] + quat->quat[2]*quat->quat[2]*vec->vec[1] +
- 2*quat->quat[3]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[3]*vec->vec[0] -
- quat->quat[3]*quat->quat[3]*vec->vec[1] + quat->quat[0]*quat->quat[0]*vec->vec[1] -
- 2*quat->quat[1]*quat->quat[0]*vec->vec[2] - quat->quat[1]*quat->quat[1]*vec->vec[1];
- rot[2] = 2*quat->quat[1]*quat->quat[3]*vec->vec[0] + 2*quat->quat[2]*quat->quat[3]*vec->vec[1] +
- quat->quat[3]*quat->quat[3]*vec->vec[2] - 2*quat->quat[0]*quat->quat[2]*vec->vec[0] -
- quat->quat[2]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[1]*vec->vec[1] -
- quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2];
- return newVectorObject(rot, 3, Py_NEW, NULL);
- }
- }
-
- PyErr_SetString(PyExc_RuntimeError, "quat_rotation(internal): internal problem rotating vector/point\n");
- return NULL;
-
-}
-
//----------------------------------MATRIX FUNCTIONS--------------------
//----------------------------------mathutils.RotationMatrix() ----------
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
@@ -696,7 +629,7 @@ PyObject *BaseMathObject_getOwner( BaseMathObject * self, void *type )
return ret;
}
-char BaseMathObject_Wrapped_doc[] = "True when this object wraps external data (readonly). **type** boolean";
+char BaseMathObject_Wrapped_doc[] = "True when this object wraps external data (readonly).\n\n:type: boolean";
PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void *type )
{
return PyBool_FromLong((self->wrapped == Py_WRAP) ? 1:0);
diff --git a/source/blender/python/generic/mathutils.h b/source/blender/python/generic/mathutils.h
index 7b83d35ff1e..85fbe3225ba 100644
--- a/source/blender/python/generic/mathutils.h
+++ b/source/blender/python/generic/mathutils.h
@@ -63,8 +63,6 @@ void BaseMathObject_dealloc(BaseMathObject * self);
PyObject *Mathutils_Init(void);
PyObject *Noise_Init(void); /* lazy, saves having own header */
-PyObject *quat_rotation(PyObject *arg1, PyObject *arg2);
-
int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);
diff --git a/source/blender/python/generic/mathutils_color.c b/source/blender/python/generic/mathutils_color.c
index 5acd03060d4..d4ab64e13c5 100644
--- a/source/blender/python/generic/mathutils_color.c
+++ b/source/blender/python/generic/mathutils_color.c
@@ -434,15 +434,15 @@ static int Color_setHSV(ColorObject * self, PyObject * value, void * type)
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Color_getseters[] = {
- {"r", (getter)Color_getChannel, (setter)Color_setChannel, "Red color channel. **type** float", (void *)0},
- {"g", (getter)Color_getChannel, (setter)Color_setChannel, "Green color channel. **type** float", (void *)1},
- {"b", (getter)Color_getChannel, (setter)Color_setChannel, "Blue color channel. **type** float", (void *)2},
+ {"r", (getter)Color_getChannel, (setter)Color_setChannel, "Red color channel.\n\n:type: float", (void *)0},
+ {"g", (getter)Color_getChannel, (setter)Color_setChannel, "Green color channel.\n\n:type: float", (void *)1},
+ {"b", (getter)Color_getChannel, (setter)Color_setChannel, "Blue color channel.\n\n:type: float", (void *)2},
- {"h", (getter)Color_getChannelHSV, (setter)Color_setChannelHSV, "HSV Hue component in [0, 1]. **type** float", (void *)0},
- {"s", (getter)Color_getChannelHSV, (setter)Color_setChannelHSV, "HSV Saturation component in [0, 1]. **type** float", (void *)1},
- {"v", (getter)Color_getChannelHSV, (setter)Color_setChannelHSV, "HSV Value component in [0, 1]. **type** float", (void *)2},
+ {"h", (getter)Color_getChannelHSV, (setter)Color_setChannelHSV, "HSV Hue component in [0, 1].\n\n:type: float", (void *)0},
+ {"s", (getter)Color_getChannelHSV, (setter)Color_setChannelHSV, "HSV Saturation component in [0, 1].\n\n:type: float", (void *)1},
+ {"v", (getter)Color_getChannelHSV, (setter)Color_setChannelHSV, "HSV Value component in [0, 1].\n\n:type: float", (void *)2},
- {"hsv", (getter)Color_getHSV, (setter)Color_setHSV, "HSV Values in [0, 1]. **type** float triplet", (void *)0},
+ {"hsv", (getter)Color_getHSV, (setter)Color_setHSV, "HSV Values in [0, 1].\n\n:type: float triplet", (void *)0},
{"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
{"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
diff --git a/source/blender/python/generic/mathutils_euler.c b/source/blender/python/generic/mathutils_euler.c
index aac65043a0a..63a04918941 100644
--- a/source/blender/python/generic/mathutils_euler.c
+++ b/source/blender/python/generic/mathutils_euler.c
@@ -615,10 +615,10 @@ static int Euler_setOrder( EulerObject * self, PyObject * value, void * type )
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Euler_getseters[] = {
- {"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis in radians. **type** float", (void *)0},
- {"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis in radians. **type** float", (void *)1},
- {"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis in radians. **type** float", (void *)2},
- {"order", (getter)Euler_getOrder, (setter)Euler_setOrder, "Euler rotation order. **type** string in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']", (void *)NULL},
+ {"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis in radians.\n\n:type: float", (void *)0},
+ {"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis in radians.\n\n:type: float", (void *)1},
+ {"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis in radians.\n\n:type: float", (void *)2},
+ {"order", (getter)Euler_getOrder, (setter)Euler_setOrder, "Euler rotation order.\n\n:type: string in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']", (void *)NULL},
{"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
{"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
diff --git a/source/blender/python/generic/mathutils_matrix.c b/source/blender/python/generic/mathutils_matrix.c
index a211386f503..9be50fe6349 100644
--- a/source/blender/python/generic/mathutils_matrix.c
+++ b/source/blender/python/generic/mathutils_matrix.c
@@ -1300,10 +1300,10 @@ static PyObject *Matrix_getIsNegative( MatrixObject * self, void *type )
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Matrix_getseters[] = {
- {"row_size", (getter)Matrix_getRowSize, (setter)NULL, "The row size of the matrix (readonly). **type** int", NULL},
- {"col_size", (getter)Matrix_getColSize, (setter)NULL, "The column size of the matrix (readonly). **type** int", NULL},
- {"median_scale", (getter)Matrix_getMedianScale, (setter)NULL, "The average scale applied to each axis (readonly). **type** float", NULL},
- {"is_negative", (getter)Matrix_getIsNegative, (setter)NULL, "True if this matrix results in a negative scale, 3x3 and 4x4 only, (readonly). **type** bool", NULL},
+ {"row_size", (getter)Matrix_getRowSize, (setter)NULL, "The row size of the matrix (readonly).\n\n:type: int", NULL},
+ {"col_size", (getter)Matrix_getColSize, (setter)NULL, "The column size of the matrix (readonly).\n\n:type: int", NULL},
+ {"median_scale", (getter)Matrix_getMedianScale, (setter)NULL, "The average scale applied to each axis (readonly).\n\n:type: float", NULL},
+ {"is_negative", (getter)Matrix_getIsNegative, (setter)NULL, "True if this matrix results in a negative scale, 3x3 and 4x4 only, (readonly).\n\n:type: bool", NULL},
{"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
{"_owner",(getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
diff --git a/source/blender/python/generic/mathutils_quat.c b/source/blender/python/generic/mathutils_quat.c
index 480b724111d..8d9fe54fa85 100644
--- a/source/blender/python/generic/mathutils_quat.c
+++ b/source/blender/python/generic/mathutils_quat.c
@@ -660,8 +660,9 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
return NULL;
}
- if(quat1 && quat2) { /* QUAT*QUAT (dot product) */
- return PyFloat_FromDouble(dot_qtqt(quat1->quat, quat2->quat));
+ if(quat1 && quat2) { /* QUAT*QUAT (cross product) */
+ mul_qt_qtqt(quat, quat1->quat, quat2->quat);
+ return newQuaternionObject(quat, Py_NEW, NULL);
}
/* the only case this can happen (for a supported type is "FLOAT*QUAT" ) */
@@ -677,12 +678,19 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
}
else { /* QUAT*SOMETHING */
if(VectorObject_Check(q2)){ /* QUAT*VEC */
+ float tvec[3];
vec = (VectorObject*)q2;
if(vec->size != 3){
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: only 3D vector rotations currently supported\n");
return NULL;
}
- return quat_rotation((PyObject*)quat1, (PyObject*)vec); /* vector updating done inside the func */
+ if(!BaseMath_ReadCallback(vec)) {
+ return NULL;
+ }
+
+ copy_v3_v3(tvec, vec->vec);
+ mul_qt_v3(quat1->quat, tvec);
+ return newVectorObject(tvec, 3, Py_NEW, NULL);
}
scalar= PyFloat_AsDouble(q2);
@@ -914,13 +922,13 @@ static struct PyMethodDef Quaternion_methods[] = {
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Quaternion_getseters[] = {
- {"w", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion W value. **type** float", (void *)0},
- {"x", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion X axis. **type** float", (void *)1},
- {"y", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Y axis. **type** float", (void *)2},
- {"z", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Z axis. **type** float", (void *)3},
- {"magnitude", (getter)Quaternion_getMagnitude, (setter)NULL, "Size of the quaternion (readonly). **type** float", NULL},
- {"angle", (getter)Quaternion_getAngle, (setter)Quaternion_setAngle, "angle of the quaternion. **type** float", NULL},
- {"axis",(getter)Quaternion_getAxisVec, (setter)Quaternion_setAxisVec, "quaternion axis as a vector. **type** :class:`Vector`", NULL},
+ {"w", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion W value.\n\n:type: float", (void *)0},
+ {"x", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion X axis.\n\n:type: float", (void *)1},
+ {"y", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Y axis.\n\n:type: float", (void *)2},
+ {"z", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Z axis.\n\n:type: float", (void *)3},
+ {"magnitude", (getter)Quaternion_getMagnitude, (setter)NULL, "Size of the quaternion (readonly).\n\n:type: float", NULL},
+ {"angle", (getter)Quaternion_getAngle, (setter)Quaternion_setAngle, "angle of the quaternion.\n\n:type: float", NULL},
+ {"axis",(getter)Quaternion_getAxisVec, (setter)Quaternion_setAxisVec, "quaternion axis as a vector.\n\n:type: :class:`Vector`", NULL},
{"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
{"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
diff --git a/source/blender/python/generic/mathutils_vector.c b/source/blender/python/generic/mathutils_vector.c
index eab03fc5911..9672878ec51 100644
--- a/source/blender/python/generic/mathutils_vector.c
+++ b/source/blender/python/generic/mathutils_vector.c
@@ -1010,13 +1010,20 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
/* VEC * MATRIX */
return row_vector_multiplication(vec1, (MatrixObject*)v2);
} else if (QuaternionObject_Check(v2)) {
- QuaternionObject *quat = (QuaternionObject*)v2; /* quat_rotation validates */
+ /* VEC * QUAT */
+ QuaternionObject *quat2 = (QuaternionObject*)v2;
+ float tvec[4];
if(vec1->size != 3) {
PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported\n");
return NULL;
}
- return quat_rotation((PyObject*)vec1, (PyObject*)quat);
+ if(!BaseMath_ReadCallback(quat2)) {
+ return NULL;
+ }
+ copy_v3_v3(tvec, vec1->vec);
+ mul_qt_v3(quat2->quat, tvec);
+ return newVectorObject(tvec, 3, Py_NEW, NULL);
}
else if (((scalar= PyFloat_AsDouble(v2)) == -1.0 && PyErr_Occurred())==0) { /* VEC*FLOAT */
int i;
@@ -1587,12 +1594,12 @@ static int Vector_setSwizzle(VectorObject *self, PyObject * value, void *closure
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Vector_getseters[] = {
- {"x", (getter)Vector_getAxis, (setter)Vector_setAxis, "Vector X axis. **type** float", (void *)0},
- {"y", (getter)Vector_getAxis, (setter)Vector_setAxis, "Vector Y axis. **type** float", (void *)1},
- {"z", (getter)Vector_getAxis, (setter)Vector_setAxis, "Vector Z axis (3D Vectors only). **type** float", (void *)2},
- {"w", (getter)Vector_getAxis, (setter)Vector_setAxis, "Vector W axis (4D Vectors only). **type** float", (void *)3},
- {"length", (getter)Vector_getLength, (setter)Vector_setLength, "Vector Length. **type** float", NULL},
- {"magnitude", (getter)Vector_getLength, (setter)Vector_setLength, "Vector Length. **type** float", NULL},
+ {"x", (getter)Vector_getAxis, (setter)Vector_setAxis, "Vector X axis.\n\n:type: float", (void *)0},
+ {"y", (getter)Vector_getAxis, (setter)Vector_setAxis, "Vector Y axis.\n\n:type: float", (void *)1},
+ {"z", (getter)Vector_getAxis, (setter)Vector_setAxis, "Vector Z axis (3D Vectors only).\n\n:type: float", (void *)2},
+ {"w", (getter)Vector_getAxis, (setter)Vector_setAxis, "Vector W axis (4D Vectors only).\n\n:type: float", (void *)3},
+ {"length", (getter)Vector_getLength, (setter)Vector_setLength, "Vector Length.\n\n:type: float", NULL},
+ {"magnitude", (getter)Vector_getLength, (setter)Vector_setLength, "Vector Length.\n\n:type: float", NULL},
{"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
{"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 6d2e45f352a..8319213a789 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -67,7 +67,7 @@ PyObject *bpy_script_paths(PyObject *self)
static char bpy_blend_paths_doc[] =
".. function:: blend_paths(absolute=False)\n"
"\n"
-" Returns a list of paths associated with this blend file.\n"
+" Returns a list of paths to external files referenced by the loaded .blend file.\n"
"\n"
" :arg absolute: When true the paths returned are made absolute.\n"
" :type absolute: boolean\n"
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index d20f2a23664..af2b5b41961 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -146,28 +146,6 @@ void BPY_update_modules( void )
bpy_context_module->ptr.data= (void *)BPy_GetContext();
}
-/*****************************************************************************
-* Description: This function creates a new Python dictionary object.
-* note: dict is owned by sys.modules["__main__"] module, reference is borrowed
-* note: important we use the dict from __main__, this is what python expects
- for 'pickle' to work as well as strings like this...
- >> foo = 10
- >> print(__import__("__main__").foo)
-*****************************************************************************/
-static PyObject *CreateGlobalDictionary(bContext *C, const char *filename)
-{
- PyInterpreterState *interp= PyThreadState_GET()->interp;
- PyObject *mod_main= PyModule_New("__main__");
- PyDict_SetItemString(interp->modules, "__main__", mod_main);
- Py_DECREF(mod_main); /* sys.modules owns now */
-
- PyModule_AddObject(mod_main, "__builtins__", interp->builtins);
- PyModule_AddStringConstant(mod_main, "__name__", "__main__");
- PyModule_AddStringConstant(mod_main, "__file__", filename); /* __file__ only for nice UI'ness */
-
- return PyModule_GetDict(mod_main);
-}
-
/* must be called before Py_Initialize */
void BPY_start_python_path(void)
{
@@ -329,13 +307,13 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
if (fn==NULL && text==NULL) {
return 0;
}
-
+
bpy_context_set(C, &gilstate);
if (text) {
char fn_dummy[FILE_MAXDIR];
bpy_text_filename_get(fn_dummy, text);
- py_dict = CreateGlobalDictionary(C, fn_dummy);
+ py_dict = bpy_namespace_dict_new(fn_dummy);
if( !text->compiled ) { /* if it wasn't already compiled, do it now */
char *buf = txt_to_buf( text );
@@ -356,7 +334,7 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
else {
FILE *fp= fopen(fn, "r");
- py_dict = CreateGlobalDictionary(C, fn);
+ py_dict = bpy_namespace_dict_new(fn);
if(fp) {
#ifdef _WIN32
@@ -500,7 +478,7 @@ int BPY_run_python_script_space(const char *modulename, const char *func)
gilstate = PyGILState_Ensure();
- py_dict = CreateGlobalDictionary(C);
+ py_dict = bpy_namespace_dict_new("<dummy>");
PyObject *module = PyImport_ImportModule(scpt->script.filename);
if (module==NULL) {
@@ -552,7 +530,7 @@ int BPY_eval_button(bContext *C, const char *expr, double *value)
bpy_context_set(C, &gilstate);
- py_dict= CreateGlobalDictionary(C, "<blender button>");
+ py_dict= bpy_namespace_dict_new("<blender button>");
mod = PyImport_ImportModule("math");
if (mod) {
@@ -623,7 +601,7 @@ int BPY_eval_string(bContext *C, const char *expr)
bpy_context_set(C, &gilstate);
- py_dict= CreateGlobalDictionary(C, "<blender string>");
+ py_dict= bpy_namespace_dict_new("<blender string>");
retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict);
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 8be9cc4cdae..ff273fa098d 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -4388,7 +4388,7 @@ static int rna_function_arg_count(FunctionRNA *func)
const ListBase *lb= RNA_function_defined_parameters(func);
PropertyRNA *parm;
Link *link;
- int count= 1;
+ int count= (RNA_function_flag(func) & FUNC_NO_SELF) ? 0 : 1;
for(link=lb->first; link; link=link->next) {
parm= (PropertyRNA*)link;
@@ -4409,7 +4409,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
const char *class_type= RNA_struct_identifier(srna);
PyObject *py_class= (PyObject*)py_data;
PyObject *base_class= RNA_struct_py_type_get(srna);
- PyObject *item, *fitem;
+ PyObject *item;
PyObject *py_arg_count;
int i, flag, arg_count, func_arg_count;
const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; // __name__
@@ -4446,25 +4446,33 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
PyErr_Clear();
}
else {
- Py_DECREF(item); /* no need to keep a ref, the class owns it */
-
- if (PyMethod_Check(item))
- fitem= PyMethod_Function(item); /* py 2.x */
- else
- fitem= item; /* py 3.x */
-
- if (PyFunction_Check(fitem)==0) {
- PyErr_Format( PyExc_TypeError, "expected %.200s, %.200s class \"%.200s\" attribute to be a function", class_type, py_class_name, RNA_function_identifier(func));
- return -1;
+ Py_DECREF(item); /* no need to keep a ref, the class owns it (technically we should keep a ref but...) */
+ if(flag & FUNC_NO_SELF) {
+ if (PyMethod_Check(item)==0) {
+ PyErr_Format( PyExc_TypeError, "expected %.200s, %.200s class \"%.200s\" attribute to be a method, not a %.200s", class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name);
+ return -1;
+ }
+ item= ((PyMethodObject *)item)->im_func;
+ }
+ else {
+ if (PyFunction_Check(item)==0) {
+ PyErr_Format( PyExc_TypeError, "expected %.200s, %.200s class \"%.200s\" attribute to be a function, not a %.200s", class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name);
+ return -1;
+ }
}
func_arg_count= rna_function_arg_count(func);
if (func_arg_count >= 0) { /* -1 if we dont care*/
- py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(fitem), "co_argcount");
+ py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(item), "co_argcount");
arg_count = PyLong_AsSsize_t(py_arg_count);
Py_DECREF(py_arg_count);
+ /* note, the number of args we check for and the number of args we give to
+ * @classmethods are different (quirk of python), this is why rna_function_arg_count() doesn't return the value -1*/
+ if(flag & FUNC_NO_SELF)
+ func_arg_count++;
+
if (arg_count != func_arg_count) {
PyErr_Format( PyExc_AttributeError, "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d", class_type, py_class_name, RNA_function_identifier(func), func_arg_count, arg_count);
return -1;
@@ -4537,6 +4545,7 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
ParameterIterator iter;
PointerRNA funcptr;
int err= 0, i, flag, ret_len=0;
+ int is_static = RNA_function_flag(func) & FUNC_NO_SELF;
PropertyRNA *pret_single= NULL;
void *retdata_single= NULL;
@@ -4544,55 +4553,64 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
PyGILState_STATE gilstate;
bContext *C= BPy_GetContext(); // XXX - NEEDS FIXING, QUITE BAD.
- bpy_context_set(C, &gilstate);
-
+
py_class= RNA_struct_py_type_get(ptr->type);
- /* exception, operators store their PyObjects for re-use */
- if(ptr->data) {
- if(RNA_struct_is_a(ptr->type, &RNA_Operator)) {
- wmOperator *op= ptr->data;
- if(op->py_instance) {
- py_class_instance= op->py_instance;
- Py_INCREF(py_class_instance);
- }
- else {
- /* store the instance here once its created */
- py_class_instance_store= &op->py_instance;
- }
- }
+ /* rare case. can happen when registering subclasses */
+ if(py_class==NULL) {
+ fprintf(stderr, "bpy_class_call(): unable to get python class for rna struct '%.200s'\n", RNA_struct_identifier(ptr->type));
+ return -1;
}
- /* end exception */
-
- if(py_class_instance==NULL)
- py_srna= pyrna_struct_CreatePyObject(ptr);
+
+ bpy_context_set(C, &gilstate);
- if(py_class_instance) {
- /* special case, instance is cached */
- }
- else if(py_srna == NULL) {
- py_class_instance = NULL;
- }
- else if(py_srna == Py_None) { /* probably wont ever happen but possible */
- Py_DECREF(py_srna);
- py_class_instance = NULL;
- }
- else {
- args = PyTuple_New(1);
- PyTuple_SET_ITEM(args, 0, py_srna);
- py_class_instance= PyObject_Call(py_class, args, NULL);
- Py_DECREF(args);
-
- if(py_class_instance == NULL) {
- err= -1; /* so the error is not overridden below */
+ if (!is_static) {
+ /* exception, operators store their PyObjects for re-use */
+ if(ptr->data) {
+ if(RNA_struct_is_a(ptr->type, &RNA_Operator)) {
+ wmOperator *op= ptr->data;
+ if(op->py_instance) {
+ py_class_instance= op->py_instance;
+ Py_INCREF(py_class_instance);
+ }
+ else {
+ /* store the instance here once its created */
+ py_class_instance_store= &op->py_instance;
+ }
+ }
+ }
+ /* end exception */
+
+ if(py_class_instance==NULL)
+ py_srna= pyrna_struct_CreatePyObject(ptr);
+
+ if(py_class_instance) {
+ /* special case, instance is cached */
+ }
+ else if(py_srna == NULL) {
+ py_class_instance = NULL;
}
- else if(py_class_instance_store) {
- *py_class_instance_store = py_class_instance;
- Py_INCREF(py_class_instance);
+ else if(py_srna == Py_None) { /* probably wont ever happen but possible */
+ Py_DECREF(py_srna);
+ py_class_instance = NULL;
+ }
+ else {
+ args = PyTuple_New(1);
+ PyTuple_SET_ITEM(args, 0, py_srna);
+ py_class_instance= PyObject_Call(py_class, args, NULL);
+ Py_DECREF(args);
+
+ if(py_class_instance == NULL) {
+ err= -1; /* so the error is not overridden below */
+ }
+ else if(py_class_instance_store) {
+ *py_class_instance_store = py_class_instance;
+ Py_INCREF(py_class_instance);
+ }
}
}
- if (py_class_instance) { /* Initializing the class worked, now run its invoke function */
+ if (is_static || py_class_instance) { /* Initializing the class worked, now run its invoke function */
PyObject *item= PyObject_GetAttrString(py_class, RNA_function_identifier(func));
// flag= RNA_function_flag(func);
@@ -4600,12 +4618,19 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
RNA_pointer_create(NULL, &RNA_Function, func, &funcptr);
args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */
- PyTuple_SET_ITEM(args, 0, py_class_instance);
+
+ if(is_static) {
+ i= 0;
+ }
+ else {
+ PyTuple_SET_ITEM(args, 0, py_class_instance);
+ i= 1;
+ }
RNA_parameter_list_begin(parms, &iter);
/* parse function parameters */
- for (i= 1; iter.valid; RNA_parameter_list_next(&iter)) {
+ for (; iter.valid; RNA_parameter_list_next(&iter)) {
parm= iter.parm;
flag= RNA_property_flag(parm);
@@ -4736,7 +4761,16 @@ void pyrna_alloc_types(void)
prop = RNA_struct_find_property(&ptr, "structs");
RNA_PROP_BEGIN(&ptr, itemptr, prop) {
- Py_DECREF(pyrna_struct_Subtype(&itemptr));
+ PyObject *item= pyrna_struct_Subtype(&itemptr);
+ if(item == NULL) {
+ if(PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ }
+ else {
+ Py_DECREF(item);
+ }
}
RNA_PROP_END;
@@ -4799,6 +4833,14 @@ static PyObject *pyrna_basetype_register(PyObject *self, PyObject *py_class)
if(srna==NULL)
return NULL;
+ /* fails in cases, cant use this check but would like to :| */
+ /*
+ if(RNA_struct_py_type_get(srna)) {
+ PyErr_Format(PyExc_ValueError, "bpy.types.register(...): %.200s's parent class %.200s is alredy registered, this is not allowed.", ((PyTypeObject*)py_class)->tp_name, RNA_struct_identifier(srna));
+ return NULL;
+ }
+ */
+
/* check that we have a register callback for this type */
reg= RNA_struct_register(srna);
diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c
index 2404442dc18..b2a7511f998 100644
--- a/source/blender/python/intern/bpy_rna_callback.c
+++ b/source/blender/python/intern/bpy_rna_callback.c
@@ -64,19 +64,28 @@ PyObject *pyrna_callback_add(BPy_StructRNA *self, PyObject *args)
char *cb_event_str= NULL;
int cb_event;
- if (!PyArg_ParseTuple(args, "OO|s:bpy_struct.callback_add", &cb_func, &cb_args, &cb_event_str))
+ if (!PyArg_ParseTuple(args, "OO!|s:bpy_struct.callback_add", &cb_func, &PyTuple_Type, &cb_args, &cb_event_str))
return NULL;
+
+ if(!PyCallable_Check(cb_func)) {
+ PyErr_SetString(PyExc_TypeError, "callback_add(): first argument isn't callable");
+ return NULL;
+ }
if(RNA_struct_is_a(self->ptr.type, &RNA_Region)) {
-
- static EnumPropertyItem region_draw_mode_items[] = {
- {REGION_DRAW_POST_VIEW, "POST_VIEW", 0, "Pose View", ""},
- {REGION_DRAW_POST_PIXEL, "POST_PIXEL", 0, "Post Pixel", ""},
- {REGION_DRAW_PRE_VIEW, "PRE_VIEW", 0, "Pre View", ""},
- {0, NULL, 0, NULL, NULL}};
-
- if(pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") < 0)
- return NULL;
+ if(cb_event_str) {
+ static EnumPropertyItem region_draw_mode_items[] = {
+ {REGION_DRAW_POST_PIXEL, "POST_PIXEL", 0, "Post Pixel", ""},
+ {REGION_DRAW_POST_VIEW, "POST_VIEW", 0, "Post View", ""},
+ {REGION_DRAW_PRE_VIEW, "PRE_VIEW", 0, "Pre View", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+ if(pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") < 0)
+ return NULL;
+ }
+ else {
+ cb_event= REGION_DRAW_POST_PIXEL;
+ }
handle= ED_region_draw_cb_activate(((ARegion *)self->ptr.data)->type, cb_region_draw, (void *)args, cb_event);
Py_INCREF(args);