diff options
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/SConscript | 3 | ||||
-rw-r--r-- | source/blender/python/doc/sphinx_doc_gen.py | 4 | ||||
-rw-r--r-- | source/blender/python/generic/bpy_internal_import.c | 23 | ||||
-rw-r--r-- | source/blender/python/generic/bpy_internal_import.h | 2 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils.c | 71 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils.h | 2 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_color.c | 14 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_euler.c | 8 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_matrix.c | 8 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_quat.c | 28 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_vector.c | 23 | ||||
-rw-r--r-- | source/blender/python/intern/bpy.c | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_interface.c | 34 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 156 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna_callback.c | 29 |
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); |