diff options
author | Arystanbek Dyussenov <arystan.d@gmail.com> | 2009-09-11 22:09:58 +0400 |
---|---|---|
committer | Arystanbek Dyussenov <arystan.d@gmail.com> | 2009-09-11 22:09:58 +0400 |
commit | 3b2ad838e8c628a468ee19ac77fb1336dd6072cf (patch) | |
tree | bc1e229f3055e4114086775122c7a47facb42679 /source/blender/python | |
parent | 7220792f187f91a2ef3eb0c930a13674b2a8a80a (diff) | |
parent | 15d77f17a40398a63f95e16607deb81257c02698 (diff) |
Merge with -r 22620:23107.
Next: update scripts and merge in 2.5.
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/CMakeLists.txt | 16 | ||||
-rw-r--r-- | source/blender/python/SConscript | 4 | ||||
-rw-r--r-- | source/blender/python/epy_doc_gen.py | 212 | ||||
-rw-r--r-- | source/blender/python/generic/bpy_internal_import.h | 9 | ||||
-rw-r--r-- | source/blender/python/generic/matrix.c | 43 | ||||
-rw-r--r-- | source/blender/python/generic/vector.c | 50 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_array.c | 515 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_interface.c | 43 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_operator.c | 35 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_operator_wrap.c | 4 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 529 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.h | 12 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_util.c | 38 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_util.h | 2 |
14 files changed, 1086 insertions, 426 deletions
diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt index 7700e6bc2aa..7abec566505 100644 --- a/source/blender/python/CMakeLists.txt +++ b/source/blender/python/CMakeLists.txt @@ -27,23 +27,23 @@ FILE(GLOB SRC intern/*.c) FILE(GLOB GENSRC generic/*.c) SET(INC - . ../../../intern/guardedalloc ../blenlib ../makesdna ../makesrna - ../blenkernel ../editors/include ../windowmanager ${PYTHON_INC} - ../../../extern/glew/include + . ../../../intern/guardedalloc ../blenlib ../makesdna ../makesrna + ../blenkernel ../editors/include ../windowmanager ${PYTHON_INC} + ../../../extern/glew/include ) IF(WITH_OPENEXR) - ADD_DEFINITIONS(-DWITH_OPENEXR) + ADD_DEFINITIONS(-DWITH_OPENEXR) ENDIF(WITH_OPENEXR) IF(WITH_QUICKTIME) - SET(INC ${INC} ${QUICKTIME_INC}) - ADD_DEFINITIONS(-DWITH_QUICKTIME) + SET(INC ${INC} ${QUICKTIME_INC}) + ADD_DEFINITIONS(-DWITH_QUICKTIME) ENDIF(WITH_QUICKTIME) IF(WITH_FFMPEG) - SET(INC ${INC} ${FFMPEG_INC}) - ADD_DEFINITIONS(-DWITH_FFMPEG) + SET(INC ${INC} ${FFMPEG_INC}) + ADD_DEFINITIONS(-DWITH_FFMPEG) ENDIF(WITH_FFMPEG) ADD_DEFINITIONS(-DWITH_CCGSUBSURF) diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript index d44cf762a0f..ca742a3646a 100644 --- a/source/blender/python/SConscript +++ b/source/blender/python/SConscript @@ -13,9 +13,9 @@ defs = [] if env['OURPLATFORM'] in ('win32-mingw', 'win32-vc','win64-vc') and env['BF_DEBUG']: defs.append('_DEBUG') -env.BlenderLib( libname = 'bf_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core'], priority = [140]) +env.BlenderLib( libname = 'bf_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core','player'], priority = [361,160]) # generic sources = env.Glob('generic/*.c') -env.BlenderLib( libname = 'bf_gen_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core'], priority = [361]) # ketsji is 360 +env.BlenderLib( libname = 'bf_gen_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core','player'], priority = [362,165]) # ketsji is 360 diff --git a/source/blender/python/epy_doc_gen.py b/source/blender/python/epy_doc_gen.py index 6a515648340..c2ef6bbc0d0 100644 --- a/source/blender/python/epy_doc_gen.py +++ b/source/blender/python/epy_doc_gen.py @@ -37,6 +37,94 @@ Generate html docs by running... # if you dont have graphvis installed ommit the --graph arg. +# GLOBALS['BASEDIR'] = './source/blender/python/doc' + +import os + +SUBMODULES = {} +INIT_SUBMODULES = {} # store initialized files + +INIT_SUBMODULES_IMPORTS = {} # dont import the same module twice + +def append_package(package_path, mod_name): + + init_path = os.path.join(os.path.dirname(package_path), "__init__.py") + + # avoid double ups + if mod_name: + imports = INIT_SUBMODULES_IMPORTS.setdefault(init_path, []) + if mod_name in imports: + return + imports.append(mod_name) + + try: + os.makedirs(os.path.dirname(init_path)) # make the dirs if they are not there + except: + pass + + # Open the new file for the first time, otherwise keep it open. + f = INIT_SUBMODULES.get(init_path) + if f == None: + f = INIT_SUBMODULES[init_path] = open(init_path, 'w') + + if mod_name: + f.write("import %s\n" % mod_name) + + return f + +def append_package_recursive(package_path, BASEPATH): + ''' + assume the last item of package_path will be a file (not a dir thats created) + ''' + + package_path = os.path.splitext(package_path)[0] # incase of .py + + try: + os.makedirs(os.path.join(BASEPATH, os.path.dirname(package_path))) # make the dirs if they are not there + except: + pass + + new_path = BASEPATH + + for mod_name in package_path.split(os.sep): + init_path = os.path.join(new_path, "__init__.py") + new_path = os.path.join(new_path, mod_name) + append_package(init_path, mod_name) + + +def open_submodule(subpath, BASEPATH): + ''' + This is a utility function that lets us quickly add submodules + ''' + + # create all the package paths leading up to this module + append_package_recursive(subpath, BASEPATH) + + module_name = os.path.basename( os.path.splitext(subpath)[0] ) + mod_path = os.path.join(BASEPATH, subpath) + + # Open the new file for the first time, otherwise keep it open. + f = SUBMODULES.get(mod_path) + if f == None: + f = SUBMODULES[mod_path] = open(mod_path, 'w') + + f = open(mod_path, 'w') + return f + +def close_all(): + for files in (INIT_SUBMODULES.values(), SUBMODULES.values()): + for f in files: + if f.name.endswith('.py'): + f_name = f.name + f.close() + + f = open(f_name, 'a') + f.write("\ndel __package__\n") # annoying, no need do show this + + + f.close() + + def range_str(val): if val < -10000000: return '-inf' if val > 10000000: return 'inf' @@ -59,6 +147,19 @@ def full_rna_struct_path(rna_struct): else: return rna_struct.identifier +def rna_id_ignore(rna_id): + if rna_id == "rna_type": + return True + + if "_OT_" in rna_id: + return True + if "_MT_" in rna_id: + return True + if "_PT_" in rna_id: + return True + + return False + def write_func(rna, ident, out, func_type): # Keyword attributes kw_args = [] # "foo = 1", "bar=0.5", "spam='ENUM'" @@ -68,7 +169,7 @@ def write_func(rna, ident, out, func_type): # Operators and functions work differently if func_type=='OPERATOR': - rna_func_name = rna_struct.identifier + rna_func_name = rna_struct.identifier.split("_OT_")[-1] rna_func_desc = rna_struct.description.strip() items = rna_struct.properties.items() else: @@ -78,7 +179,7 @@ def write_func(rna, ident, out, func_type): for rna_prop_identifier, rna_prop in items: - if rna_prop_identifier=='rna_type': + if rna_id_ignore(rna_prop_identifier): continue # clear vars @@ -196,7 +297,7 @@ def write_func(rna, ident, out, func_type): -def rna2epy(target_path): +def rna2epy(BASEPATH): # Use for faster lookups # use rna_struct.identifier as the key for each dict @@ -255,7 +356,7 @@ def rna2epy(target_path): for rna_prop_identifier, rna_prop in rna_struct.properties.items(): if rna_prop_identifier=='RNA': continue - if rna_prop_identifier=='rna_type': continue + if rna_id_ignore(rna_prop_identifier): continue if rna_prop_identifier in rna_base_prop_keys: continue # does this prop exist in our parent class, if so skip rna_desc = rna_prop.description.strip() @@ -320,7 +421,10 @@ def rna2epy(target_path): for child in rna_children_dict[identifier]: write_struct(child, ident + '\t') - out = open(target_path, 'w') + + + # out = open(target_path, 'w') + out = open_submodule("types.py", BASEPATH) # bpy.types def base_id(rna_struct): try: return rna_struct.base.identifier @@ -343,21 +447,23 @@ def rna2epy(target_path): #if not rna_type_name.startswith('__'): identifier = rna_struct.identifier - structs.append( (base_id(rna_struct), identifier, rna_struct) ) - - # Simple lookup - rna_struct_dict[identifier] = rna_struct - - # Store full rna path 'GameObjectSettings' -> 'Object.GameObjectSettings' - rna_full_path_dict[identifier] = full_rna_struct_path(rna_struct) - - # Store a list of functions, remove inherited later - rna_functions_dict[identifier]= list(rna_struct.functions) - - # fill in these later - rna_children_dict[identifier]= [] - rna_references_dict[identifier]= [] + if not rna_id_ignore(identifier): + structs.append( (base_id(rna_struct), identifier, rna_struct) ) + + # Simple lookup + rna_struct_dict[identifier] = rna_struct + + # Store full rna path 'GameObjectSettings' -> 'Object.GameObjectSettings' + rna_full_path_dict[identifier] = full_rna_struct_path(rna_struct) + + # Store a list of functions, remove inherited later + rna_functions_dict[identifier]= list(rna_struct.functions) + + + # fill in these later + rna_children_dict[identifier]= [] + rna_references_dict[identifier]= [] else: @@ -417,7 +523,7 @@ def rna2epy(target_path): for rna_prop_identifier, rna_prop in rna_struct.properties.items(): if rna_prop_identifier=='RNA': continue - if rna_prop_identifier=='rna_type': continue + if rna_id_ignore(rna_prop_identifier): continue if rna_prop_identifier in rna_base_prop_keys: continue try: rna_prop_ptr = rna_prop.fixed_type @@ -431,7 +537,7 @@ def rna2epy(target_path): for rna_prop_identifier, rna_prop in rna_func.parameters.items(): if rna_prop_identifier=='RNA': continue - if rna_prop_identifier=='rna_type': continue + if rna_id_ignore(rna_prop_identifier): continue if rna_prop_identifier in rna_base_func_keys: continue @@ -476,6 +582,7 @@ def rna2epy(target_path): # # We could also just run.... # os.system('epydoc source/blender/python/doc/rna.py -o ./source/blender/python/doc/html -v') + target_path = os.path.join(BASEPATH, "dump.py") # XXX - used for other funcs # Write graphviz out= open(target_path.replace('.py', '.dot'), 'w') @@ -546,8 +653,8 @@ def rna2epy(target_path): out.write('%s\n' % w) -def op2epy(target_path): - out = open(target_path, 'w') +def op2epy(BASEPATH): + # out = open(target_path, 'w') op_mods = dir(bpy.ops) op_mods.remove('add') @@ -556,26 +663,73 @@ def op2epy(target_path): for op_mod_name in sorted(op_mods): if op_mod_name.startswith('__'): continue + + # open the submodule + mod_path = os.path.join("ops", op_mod_name + ".py") + out = open_submodule(mod_path, BASEPATH) + op_mod = getattr(bpy.ops, op_mod_name) - operators = dir(op_mod) for op in sorted(operators): # rna = getattr(bpy.types, op).__rna__ rna = getattr(op_mod, op).get_rna() write_func(rna, '', out, 'OPERATOR') + + out.write('\n') + out.close() + +def misc2epy(BASEPATH): + ''' + Hard coded modules, try to avoid adding stuff here + ''' - out.write('\n') - out.close() + f = append_package(os.path.join(BASEPATH, ""), ""); # add a slash on the end of the base path + f.write(''' +""" +@type data: L{bpy.types.Main} +@var data: blender data is accessed from here +""" +''') + + f = open_submodule("props.py", BASEPATH) + f.write(''' +MAX_INT= 2**31 +MAX_FLOAT= 1e+37 +def BoolProperty(attr, name="", description="", default=False): + """ + return a new bool property + """ +def IntProperty(attr, name="", description="", min=-MAX_INT, max=MAX_INT, soft_min=-MAX_INT, soft_max=MAX_INT, default=0): + """ + return a new int property + """ +def FloatProperty(attr, name="", description="", min=-MAX_FLOAT, max=MAX_FLOAT, soft_min=-MAX_FLOAT, soft_max=MAX_FLOAT, default=0.0): + """ + return a new float property + """ +def StringProperty(attr, name="", description="", maxlen=0, default=""): + """ + return a new string property + """ +def EnumProperty(attr, items, name="", description="", default=""): + """ + return a new enum property + """ +''') + if __name__ == '__main__': if 'bpy' not in dir(): print("\nError, this script must run from inside blender2.5") print(script_help_msg) - else: - rna2epy('source/blender/python/doc/rna.py') - op2epy('source/blender/python/doc/bpyoperator.py') + misc2epy('source/blender/python/doc/bpy') # first to write in info in some of the modules. + rna2epy('source/blender/python/doc/bpy') + op2epy('source/blender/python/doc/bpy') + + + close_all() import sys sys.exit() diff --git a/source/blender/python/generic/bpy_internal_import.h b/source/blender/python/generic/bpy_internal_import.h index c93d930dab0..4e761fe8da0 100644 --- a/source/blender/python/generic/bpy_internal_import.h +++ b/source/blender/python/generic/bpy_internal_import.h @@ -31,6 +31,15 @@ #ifndef EXPP_bpy_import_h #define EXPP_bpy_import_h +/* python redefines :/ */ +#ifdef _POSIX_C_SOURCE +#undef _POSIX_C_SOURCE +#endif + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + #include <Python.h> #include "compile.h" /* for the PyCodeObject */ #include "eval.h" /* for PyEval_EvalCode */ diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c index be3e704460a..edb6fb7af63 100644 --- a/source/blender/python/generic/matrix.c +++ b/source/blender/python/generic/matrix.c @@ -598,18 +598,18 @@ static PyObject *Matrix_repr(MatrixObject * self) return NULL; BLI_strncpy(str,"",1024); - for(x = 0; x < self->rowSize; x++){ + for(x = 0; x < self->colSize; x++){ sprintf(buffer, "["); strcat(str,buffer); - for(y = 0; y < (self->colSize - 1); y++) { - sprintf(buffer, "%.6f, ", self->matrix[x][y]); + for(y = 0; y < (self->rowSize - 1); y++) { + sprintf(buffer, "%.6f, ", self->matrix[y][x]); strcat(str,buffer); } - if(x < (self->rowSize-1)){ - sprintf(buffer, "%.6f](matrix [row %d])\n", self->matrix[x][y], x); + if(x < (self->colSize-1)){ + sprintf(buffer, "%.6f](matrix [row %d])\n", self->matrix[y][x], x); strcat(str,buffer); }else{ - sprintf(buffer, "%.6f](matrix [row %d])", self->matrix[x][y], x); + sprintf(buffer, "%.6f](matrix [row %d])", self->matrix[y][x], x); strcat(str,buffer); } } @@ -703,7 +703,7 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob) return -1; if(i >= self->rowSize || i < 0){ - PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: bad row\n"); + PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: bad column\n"); return -1; } @@ -933,21 +933,21 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) } if(mat1 && mat2) { /*MATRIX * MATRIX*/ - if(mat1->colSize != mat2->rowSize){ + if(mat1->rowSize != mat2->colSize){ PyErr_SetString(PyExc_AttributeError,"Matrix multiplication: matrix A rowsize must equal matrix B colsize"); return NULL; } - for(x = 0; x < mat1->rowSize; x++) { - for(y = 0; y < mat2->colSize; y++) { - for(z = 0; z < mat1->colSize; z++) { - dot += (mat1->matrix[x][z] * mat2->matrix[z][y]); + for(x = 0; x < mat2->rowSize; x++) { + for(y = 0; y < mat1->colSize; y++) { + for(z = 0; z < mat1->rowSize; z++) { + dot += (mat1->matrix[z][y] * mat2->matrix[x][z]); } - mat[((x * mat1->rowSize) + y)] = (float)dot; + mat[((x * mat1->colSize) + y)] = (float)dot; dot = 0.0f; } } - return newMatrixObject(mat, mat1->rowSize, mat2->colSize, Py_NEW, NULL); + return newMatrixObject(mat, mat2->rowSize, mat1->colSize, Py_NEW, NULL); } if(mat1==NULL){ @@ -1288,9 +1288,9 @@ PyObject *newMatrixObject_cb(PyObject *cb_user, int rowSize, int colSize, int cb //----------------column_vector_multiplication (internal)--------- //COLUMN VECTOR Multiplication (Matrix X Vector) -// [1][2][3] [a] -// [4][5][6] * [b] -// [7][8][9] [c] +// [1][4][7] [a] +// [2][5][8] * [b] +// [3][6][9] [c] //vector/matrix multiplication IS NOT COMMUTATIVE!!!! static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec) { @@ -1312,11 +1312,12 @@ static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* for(x = 0; x < vec->size; x++){ vecCopy[x] = vec->vec[x]; - } + } + vecNew[3] = 1.0f; - for(x = 0; x < mat->rowSize; x++) { - for(y = 0; y < mat->colSize; y++) { - dot += mat->matrix[x][y] * vecCopy[y]; + for(x = 0; x < mat->colSize; z++) { + for(y = 0; y < mat->rowSize; y++) { + dot += mat->matrix[y][x] * vecCopy[y]; } vecNew[z++] = (float)dot; dot = 0.0f; diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c index 923c4bbe58a..605f45be128 100644 --- a/source/blender/python/generic/vector.c +++ b/source/blender/python/generic/vector.c @@ -168,7 +168,7 @@ static PyObject *Vector_Resize2D(VectorObject * self) return NULL; } if(self->cb_user) { - PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner"); + PyErr_SetString(PyExc_TypeError, "vector.resize2d(): cannot resize a vector that has an owner"); return NULL; } @@ -191,7 +191,7 @@ static PyObject *Vector_Resize3D(VectorObject * self) return NULL; } if(self->cb_user) { - PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner"); + PyErr_SetString(PyExc_TypeError, "vector.resize3d(): cannot resize a vector that has an owner"); return NULL; } @@ -354,18 +354,12 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args ) /*----------------------------Vector.reflect(mirror) ---------------------- return a reflected vector on the mirror normal - ((2 * DotVecs(vec, mirror)) * mirror) - vec - using arithb.c would be nice here */ + vec - ((2 * DotVecs(vec, mirror)) * mirror) +*/ static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value ) { - float mirror[3]; - float vec[3]; - float reflect[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - float dot2; - - /* for normalizing */ - int i; - float norm = 0.0f; + float mirror[3], vec[3]; + float reflect[3] = {0.0f, 0.0f, 0.0f}; if (!VectorObject_Check(value)) { PyErr_SetString( PyExc_TypeError, "vec.reflect(value): expected a vector argument" ); @@ -380,26 +374,12 @@ static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value ) if (value->size > 2) mirror[2] = value->vec[2]; else mirror[2] = 0.0; - /* normalize, whos idea was it not to use arithb.c? :-/ */ - for(i = 0; i < 3; i++) { - norm += mirror[i] * mirror[i]; - } - norm = (float) sqrt(norm); - for(i = 0; i < 3; i++) { - mirror[i] /= norm; - } - /* done */ - vec[0] = self->vec[0]; vec[1] = self->vec[1]; if (self->size > 2) vec[2] = self->vec[2]; else vec[2] = 0.0; - dot2 = 2 * vec[0]*mirror[0]+vec[1]*mirror[1]+vec[2]*mirror[2]; - - reflect[0] = (dot2 * mirror[0]) - vec[0]; - reflect[1] = (dot2 * mirror[1]) - vec[1]; - reflect[2] = (dot2 * mirror[2]) - vec[2]; + VecReflect(reflect, vec, mirror); return newVectorObject(reflect, self->size, Py_NEW, NULL); } @@ -1955,9 +1935,9 @@ PyObject *newVectorObject_cb(PyObject *cb_user, int size, int cb_type, int cb_su //-----------------row_vector_multiplication (internal)----------- //ROW VECTOR Multiplication - Vector X Matrix -//[x][y][z] * [1][2][3] -// [4][5][6] -// [7][8][9] +//[x][y][z] * [1][4][7] +// [2][5][8] +// [3][6][9] //vector/matrix multiplication IS NOT COMMUTATIVE!!!! static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat) { @@ -1966,7 +1946,7 @@ static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat int x, y, z = 0, vec_size = vec->size; if(mat->colSize != vec_size){ - if(mat->rowSize == 4 && vec_size != 3){ + if(mat->colSize == 4 && vec_size != 3){ PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same"); return NULL; }else{ @@ -1980,11 +1960,11 @@ static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat for(x = 0; x < vec_size; x++){ vecCopy[x] = vec->vec[x]; } - + vecNew[3] = 1.0f; //muliplication - for(x = 0; x < mat->colSize; x++) { - for(y = 0; y < mat->rowSize; y++) { - dot += mat->matrix[y][x] * vecCopy[y]; + for(x = 0; x < mat->rowSize; x++) { + for(y = 0; y < mat->colSize; y++) { + dot += mat->matrix[x][y] * vecCopy[y]; } vecNew[z++] = (float)dot; dot = 0.0f; diff --git a/source/blender/python/intern/bpy_array.c b/source/blender/python/intern/bpy_array.c new file mode 100644 index 00000000000..f11c95e7ed5 --- /dev/null +++ b/source/blender/python/intern/bpy_array.c @@ -0,0 +1,515 @@ +/** + * + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Arystanbek Dyussenov + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "Python.h" + +#include "bpy_rna.h" + +#include "RNA_access.h" + +#include "BLI_string.h" + +#include "BKE_global.h" + +#include "MEM_guardedalloc.h" + +#define MAX_ARRAY_DIMENSION 10 + +typedef void (*ItemConvertFunc)(PyObject *, char *); +typedef int (*ItemTypeCheckFunc)(PyObject *); +typedef void (*RNA_SetArrayFunc)(PointerRNA *, PropertyRNA *, const char *); +typedef void (*RNA_SetIndexFunc)(PointerRNA *, PropertyRNA *, int index, void *); + +/* + arr[3][4][5] + 0 1 2 <- dimension index +*/ + +/* + arr[2] = x + + py_to_array_index(arraydim=0, arrayoffset=0, index=2) + validate_array(lvalue_dim=0) + ... make real index ... +*/ + +/* arr[3]=x, self->arraydim is 0, lvalue_dim is 1 */ +/* Ensures that a python sequence has expected number of items/sub-items and items are of desired type. */ +static int validate_array_type(PyObject *seq, int dim, int totdim, int dimsize[], + ItemTypeCheckFunc check_item_type, const char *item_type_str, const char *error_prefix) +{ + int i; + + /* not the last dimension */ + if (dim + 1 < totdim) { + /* check that a sequence contains dimsize[dim] items */ + + for (i= 0; i < PySequence_Length(seq); i++) { + PyObject *item; + int ok= 1; + item= PySequence_GetItem(seq, i); + + if (!PySequence_Check(item)) { + /* BLI_snprintf(error_str, error_str_size, "expected a sequence of %s", item_type_str); */ + PyErr_Format(PyExc_TypeError, "%s expected a sequence of %s", error_prefix, item_type_str); + ok= 0; + } + /* arr[3][4][5] + dimsize[1]=4 + dimsize[2]=5 + + dim=0 */ + else if (PySequence_Length(item) != dimsize[dim + 1]) { + /* BLI_snprintf(error_str, error_str_size, "sequences of dimension %d should contain %d items", (int)dim + 1, (int)dimsize[dim + 1]); */ + PyErr_Format(PyExc_ValueError, "%s sequences of dimension %d should contain %d items", error_prefix, (int)dim + 1, (int)dimsize[dim + 1]); + ok= 0; + } + else if (!validate_array_type(item, dim + 1, totdim, dimsize, check_item_type, item_type_str, error_prefix)) { + ok= 0; + } + + Py_DECREF(item); + + if (!ok) + return 0; + } + } + else { + /* check that items are of correct type */ + for (i= 0; i < PySequence_Length(seq); i++) { + PyObject *item= PySequence_GetItem(seq, i); + + if (!check_item_type(item)) { + Py_DECREF(item); + + /* BLI_snprintf(error_str, error_str_size, "sequence items should be of type %s", item_type_str); */ + PyErr_Format(PyExc_TypeError, "sequence items should be of type %s", item_type_str); + return 0; + } + + Py_DECREF(item); + } + } + + return 1; +} + +/* Returns the number of items in a single- or multi-dimensional sequence. */ +static int count_items(PyObject *seq) +{ + int totitem= 0; + + if (PySequence_Check(seq)) { + int i; + for (i= 0; i < PySequence_Length(seq); i++) { + PyObject *item= PySequence_GetItem(seq, i); + totitem += count_items(item); + Py_DECREF(item); + } + } + else + totitem= 1; + + return totitem; +} + +/* Modifies property array length if needed and PROP_DYNAMIC flag is set. */ +static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, int *totitem, const char *error_prefix) +{ + int dimsize[MAX_ARRAY_DIMENSION]; + int tot, totdim, len; + + tot= count_items(rvalue); + totdim= RNA_property_array_dimension(ptr, prop, dimsize); + + if ((RNA_property_flag(prop) & PROP_DYNAMIC) && lvalue_dim == 0) { + if (RNA_property_array_length(ptr, prop) != tot) { +#if 0 + /* length is flexible */ + if (!RNA_property_dynamic_array_set_length(ptr, prop, tot)) { + /* BLI_snprintf(error_str, error_str_size, "%s.%s: array length cannot be changed to %d", RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot); */ + PyErr_Format(PyExc_ValueError, "%s %s.%s: array length cannot be changed to %d", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot); + return 0; + } +#else + PyErr_Format(PyExc_ValueError, "%s %s.%s: array length cannot be changed to %d", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot); + return 0; +#endif + } + + len= tot; + } + else { + /* length is a constraint */ + if (!lvalue_dim) { + len= RNA_property_array_length(ptr, prop); + } + /* array item assignment */ + else { + int i; + + len= 1; + + /* arr[3][4][5] + + arr[2] = x + dimsize={4, 5} + dimsize[1] = 4 + dimsize[2] = 5 + lvalue_dim=0, totdim=3 + + arr[2][3] = x + lvalue_dim=1 + + arr[2][3][4] = x + lvalue_dim=2 */ + for (i= lvalue_dim; i < totdim; i++) + len *= dimsize[i]; + } + + if (tot != len) { + /* BLI_snprintf(error_str, error_str_size, "sequence must have length of %d", len); */ + PyErr_Format(PyExc_ValueError, "%s sequence must have %d items total", error_prefix, len); + return 0; + } + } + + *totitem= len; + + return 1; +} + +static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, ItemTypeCheckFunc check_item_type, const char *item_type_str, int *totitem, const char *error_prefix) +{ + int dimsize[MAX_ARRAY_DIMENSION]; + int totdim= RNA_property_array_dimension(ptr, prop, dimsize); + + /* validate type first because length validation may modify property array length */ + + if (!validate_array_type(rvalue, lvalue_dim, totdim, dimsize, check_item_type, item_type_str, error_prefix)) + return 0; + + return validate_array_length(rvalue, ptr, prop, lvalue_dim, totitem, error_prefix); +} + +static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, int dim, char *data, unsigned int item_size, int *index, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index) +{ + unsigned int i; + int totdim= RNA_property_array_dimension(ptr, prop, NULL); + + for (i= 0; i < PySequence_Length(seq); i++) { + PyObject *item= PySequence_GetItem(seq, i); + + if (dim + 1 < totdim) { + data= copy_values(item, ptr, prop, dim + 1, data, item_size, index, convert_item, rna_set_index); + } + else { + if (!data) { + char value[sizeof(int)]; + + convert_item(item, value); + rna_set_index(ptr, prop, *index, value); + *index = *index + 1; + } + else { + convert_item(item, data); + data += item_size; + } + } + + Py_DECREF(item); + } + + return data; +} + +static int py_to_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix) +{ + int totdim, dim_size[MAX_ARRAY_DIMENSION]; + int totitem; + char *data= NULL; + + totdim= RNA_property_array_dimension(ptr, prop, dim_size); + + if (!validate_array(py, ptr, prop, 0, check_item_type, item_type_str, &totitem, error_prefix)) { + return 0; + } + + if (totitem) { + if (!param_data || RNA_property_flag(prop) & PROP_DYNAMIC) + data= MEM_callocN(item_size * totitem, "pyrna primitive type array"); + else + data= param_data; + + copy_values(py, ptr, prop, 0, data, item_size, NULL, convert_item, NULL); + + if (param_data) { + if (RNA_property_flag(prop) & PROP_DYNAMIC) { + /* not freeing allocated mem, RNA_parameter_list_free will do this */ + *(char**)param_data= data; + } + } + else { + /* NULL can only pass through in case RNA property arraylength is 0 (impossible?) */ + rna_set_array(ptr, prop, data); + MEM_freeN(data); + } + } + + return 1; +} + +static int py_to_array_index(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, int arrayoffset, int index, ItemTypeCheckFunc check_item_type, const char *item_type_str, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index, const char *error_prefix) +{ + int totdim, dimsize[MAX_ARRAY_DIMENSION]; + int totitem, i; + + totdim= RNA_property_array_dimension(ptr, prop, dimsize); + + /* convert index */ + + /* arr[3][4][5] + + arr[2] = x + lvalue_dim=0, index = 0 + 2 * 4 * 5 + + arr[2][3] = x + lvalue_dim=1, index = 40 + 3 * 5 */ + + lvalue_dim++; + + for (i= lvalue_dim; i < totdim; i++) + index *= dimsize[i]; + + index += arrayoffset; + + if (!validate_array(py, ptr, prop, lvalue_dim, check_item_type, item_type_str, &totitem, error_prefix)) + return 0; + + if (totitem) + copy_values(py, ptr, prop, lvalue_dim, NULL, 0, &index, convert_item, rna_set_index); + + return 1; +} + +static void py_to_float(PyObject *py, char *data) +{ + *(float*)data= (float)PyFloat_AsDouble(py); +} + +static void py_to_int(PyObject *py, char *data) +{ + *(int*)data= (int)PyLong_AsSsize_t(py); +} + +static void py_to_bool(PyObject *py, char *data) +{ + *(int*)data= (int)PyObject_IsTrue(py); +} + +static int py_float_check(PyObject *py) +{ + /* accept both floats and integers */ + return PyFloat_Check(py) || PyLong_Check(py); +} + +static int py_int_check(PyObject *py) +{ + /* accept only integers */ + return PyLong_Check(py); +} + +static int py_bool_check(PyObject *py) +{ + return PyBool_Check(py); +} + +static void float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value) +{ + RNA_property_float_set_index(ptr, prop, index, *(float*)value); +} + +static void int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value) +{ + RNA_property_int_set_index(ptr, prop, index, *(int*)value); +} + +static void bool_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value) +{ + RNA_property_boolean_set_index(ptr, prop, index, *(int*)value); +} + +int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix) +{ + int ret; + switch (RNA_property_type(prop)) { + case PROP_FLOAT: + ret= py_to_array(py, ptr, prop, param_data, py_float_check, "float", sizeof(float), py_to_float, (RNA_SetArrayFunc)RNA_property_float_set_array, error_prefix); + break; + case PROP_INT: + ret= py_to_array(py, ptr, prop, param_data, py_int_check, "int", sizeof(int), py_to_int, (RNA_SetArrayFunc)RNA_property_int_set_array, error_prefix); + break; + case PROP_BOOLEAN: + ret= py_to_array(py, ptr, prop, param_data, py_bool_check, "boolean", sizeof(int), py_to_bool, (RNA_SetArrayFunc)RNA_property_boolean_set_array, error_prefix); + break; + default: + PyErr_SetString(PyExc_TypeError, "not an array type"); + ret= 0; + } + + return ret; +} + +int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, int index, PyObject *py, const char *error_prefix) +{ + int ret; + switch (RNA_property_type(prop)) { + case PROP_FLOAT: + ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, py_float_check, "float", py_to_float, float_set_index, error_prefix); + break; + case PROP_INT: + ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, py_int_check, "int", py_to_int, int_set_index, error_prefix); + break; + case PROP_BOOLEAN: + ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, py_bool_check, "boolean", py_to_bool, bool_set_index, error_prefix); + break; + default: + PyErr_SetString(PyExc_TypeError, "not an array type"); + ret= 0; + } + + return ret; +} + +static PyObject *pyrna_array_item(PointerRNA *ptr, PropertyRNA *prop, int index) +{ + PyObject *item; + + switch (RNA_property_type(prop)) { + case PROP_FLOAT: + item= PyFloat_FromDouble(RNA_property_float_get_index(ptr, prop, index)); + break; + case PROP_BOOLEAN: + item= PyBool_FromLong(RNA_property_boolean_get_index(ptr, prop, index)); + break; + case PROP_INT: + item= PyLong_FromSsize_t(RNA_property_int_get_index(ptr, prop, index)); + break; + default: + PyErr_SetString(PyExc_TypeError, "not an array type"); + item= NULL; + } + + return item; +} + +#if 0 +/* XXX this is not used (and never will?) */ +/* Given an array property, creates an N-dimensional tuple of values. */ +static PyObject *pyrna_py_from_array_internal(PointerRNA *ptr, PropertyRNA *prop, int dim, int *index) +{ + PyObject *tuple; + int i, len; + int totdim= RNA_property_array_dimension(ptr, prop, NULL); + + len= RNA_property_multi_array_length(ptr, prop, dim); + + tuple= PyTuple_New(len); + + for (i= 0; i < len; i++) { + PyObject *item; + + if (dim + 1 < totdim) + item= pyrna_py_from_array_internal(ptr, prop, dim + 1, index); + else { + item= pyrna_array_item(ptr, prop, *index); + *index= *index + 1; + } + + if (!item) { + Py_DECREF(tuple); + return NULL; + } + + PyTuple_SetItem(tuple, i, item); + } + + return tuple; +} +#endif + +PyObject *pyrna_py_from_array_index(BPy_PropertyRNA *self, int index) +{ + int totdim, i, len; + int dimsize[MAX_ARRAY_DIMENSION]; + BPy_PropertyRNA *ret= NULL; + + /* just in case check */ + len= RNA_property_multi_array_length(&self->ptr, self->prop, self->arraydim); + if (index >= len || index < 0) { + /* this shouldn't happen because higher level funcs must check for invalid index */ + if (G.f & G_DEBUG) printf("pyrna_py_from_array_index: invalid index %d for array with length=%d\n", index, len); + + PyErr_SetString(PyExc_IndexError, "out of range"); + return NULL; + } + + totdim= RNA_property_array_dimension(&self->ptr, self->prop, dimsize); + + if (self->arraydim + 1 < totdim) { + ret= (BPy_PropertyRNA*)pyrna_prop_CreatePyObject(&self->ptr, self->prop); + ret->arraydim= self->arraydim + 1; + + /* arr[3][4][5] + + x = arr[2] + index = 0 + 2 * 4 * 5 + + x = arr[2][3] + index = offset + 3 * 5 */ + + for (i= self->arraydim + 1; i < totdim; i++) + index *= dimsize[i]; + + ret->arrayoffset= self->arrayoffset + index; + } + else { + index = self->arrayoffset + index; + ret= (BPy_PropertyRNA*)pyrna_array_item(&self->ptr, self->prop, index); + } + + return (PyObject*)ret; +} + +PyObject *pyrna_py_from_array(PointerRNA *ptr, PropertyRNA *prop) +{ + PyObject *ret; + + ret= pyrna_math_object_from_array(ptr, prop); + + /* is this a maths object? */ + if (ret) return ret; + + return pyrna_prop_CreatePyObject(ptr, prop); +} diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index ae2f4244eac..3e089fffe6c 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -1,13 +1,37 @@ - +/** + * $Id: + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Michel Selten, Willian P. Germano, Stephen Swaney, + * Chris Keith, Chris Want, Ken Hughes, Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> -#ifndef WIN32 -#include <dirent.h> -#else -#include "BLI_winstuff.h" + +/* grr, python redefines */ +#ifdef _POSIX_C_SOURCE +#undef _POSIX_C_SOURCE #endif #include <Python.h> @@ -20,6 +44,12 @@ #include "bpy_sys.h" #include "bpy_util.h" +#ifndef WIN32 +#include <dirent.h> +#else +#include "BLI_winstuff.h" +#endif + #include "DNA_anim_types.h" #include "DNA_space_types.h" #include "DNA_text_types.h" @@ -27,6 +57,7 @@ #include "MEM_guardedalloc.h" #include "BLI_util.h" +#include "BLI_storage.h" #include "BLI_fileops.h" #include "BLI_string.h" @@ -592,7 +623,7 @@ void BPY_run_ui_scripts(bContext *C, int reload) } } #ifndef __linux__ - else if( BLI_join_dirfile(path, dirname, de->d_name), S_ISDIR(BLI_exists(path))) { + else if( BLI_join_dirfile(path, dirname, de->d_name), S_ISDIR(BLI_exist(path))) { #else else if(de->d_type==DT_DIR) { BLI_join_dirfile(path, dirname, de->d_name); diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index e431f2a21e9..062db42e0e9 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -40,42 +40,23 @@ #include "BKE_utildefines.h" -/* 'self' stores the operator string */ static PyObject *pyop_call( PyObject * self, PyObject * args) { wmOperatorType *ot; int error_val = 0; PointerRNA ptr; - char *opname; - PyObject *kw= NULL; + char *opname; + PyObject *kw= NULL; /* optional args */ + + /* note that context is an int, python does the conversion in this case */ + int context= WM_OP_EXEC_DEFAULT; // XXX Todo, work out a better solution for passing on context, could make a tuple from self and pack the name and Context into it... bContext *C = BPy_GetContext(); - - switch(PyTuple_Size(args)) { - case 2: - kw = PyTuple_GET_ITEM(args, 1); - - if(!PyDict_Check(kw)) { - PyErr_SetString( PyExc_AttributeError, "bpy.__ops__.call: expected second arg to be a dict"); - return NULL; - } - /* pass through */ - case 1: - opname = _PyUnicode_AsString(PyTuple_GET_ITEM(args, 0)); - - if(opname==NULL) { - PyErr_SetString( PyExc_AttributeError, "bpy.__ops__.call: expected the first arg to be a string"); - return NULL; - } - break; - default: - PyErr_SetString( PyExc_AttributeError, "bpy.__ops__.call: expected a string and optional dict"); + if (!PyArg_ParseTuple(args, "s|O!i:bpy.__ops__.call", &opname, &PyDict_Type, &kw, &context)) return NULL; - } - ot= WM_operatortype_find(opname, TRUE); @@ -88,7 +69,7 @@ static PyObject *pyop_call( PyObject * self, PyObject * args) PyErr_SetString( PyExc_SystemError, "bpy.__ops__.call: operator poll() function failed, context is incorrect"); return NULL; } - + /* WM_operator_properties_create(&ptr, opname); */ /* Save another lookup */ RNA_pointer_create(NULL, ot->srna, NULL, &ptr); @@ -102,7 +83,7 @@ static PyObject *pyop_call( PyObject * self, PyObject * args) BKE_reports_init(&reports, RPT_STORE); - WM_operator_call_py(C, ot, &ptr, &reports); + WM_operator_call_py(C, ot, context, &ptr, &reports); if(BPy_reports_to_error(&reports)) error_val = -1; diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index 9a74bf0aee8..0a487a8dbe8 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -228,7 +228,7 @@ static int PYTHON_OT_invoke(bContext *C, wmOperator *op, wmEvent *event) return PYTHON_OT_generic(PYOP_INVOKE, C, op, event); } -static int PYTHON_OT_exec(bContext *C, wmOperator *op) +static int PYTHON_OT_execute(bContext *C, wmOperator *op) { return PYTHON_OT_generic(PYOP_EXEC, C, op, NULL); } @@ -268,7 +268,7 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata) if (PyObject_HasAttrString(py_class, "invoke")) ot->invoke= PYTHON_OT_invoke; if (PyObject_HasAttrString(py_class, "execute")) - ot->exec= PYTHON_OT_exec; + ot->exec= PYTHON_OT_execute; if (PyObject_HasAttrString(py_class, "poll")) ot->poll= PYTHON_OT_poll; diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 0f031318446..8395e5c82e4 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -130,6 +130,70 @@ Mathutils_Callback mathutils_rna_matrix_cb = { (BaseMathSetIndexFunc) NULL }; +PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) +{ + PyObject *ret= NULL; + +#ifdef USE_MATHUTILS + int type, subtype, totdim; + int len; + + len= RNA_property_array_length(ptr, prop); + type= RNA_property_type(prop); + subtype= RNA_property_subtype(prop); + totdim= RNA_property_array_dimension(ptr, prop, NULL); + + if (type != PROP_FLOAT) return NULL; + + if (totdim == 1 || (totdim == 2 && subtype == PROP_MATRIX)) { + ret = pyrna_prop_CreatePyObject(ptr, prop); + + switch(RNA_property_subtype(prop)) { + case PROP_TRANSLATION: + case PROP_DIRECTION: + case PROP_VELOCITY: + case PROP_ACCELERATION: + case PROP_XYZ: + if(len>=2 && len <= 4) { + PyObject *vec_cb= newVectorObject_cb(ret, len, mathutils_rna_array_cb_index, FALSE); + Py_DECREF(ret); /* the vector owns now */ + ret= vec_cb; /* return the vector instead */ + } + break; + case PROP_MATRIX: + if(len==16) { + PyObject *mat_cb= newMatrixObject_cb(ret, 4,4, mathutils_rna_matrix_cb_index, FALSE); + Py_DECREF(ret); /* the matrix owns now */ + ret= mat_cb; /* return the matrix instead */ + } + else if (len==9) { + PyObject *mat_cb= newMatrixObject_cb(ret, 3,3, mathutils_rna_matrix_cb_index, FALSE); + Py_DECREF(ret); /* the matrix owns now */ + ret= mat_cb; /* return the matrix instead */ + } + break; + case PROP_EULER: + case PROP_QUATERNION: + if(len==3) { /* euler */ + PyObject *eul_cb= newEulerObject_cb(ret, mathutils_rna_array_cb_index, FALSE); + Py_DECREF(ret); /* the matrix owns now */ + ret= eul_cb; /* return the matrix instead */ + } + else if (len==4) { + PyObject *quat_cb= newQuaternionObject_cb(ret, mathutils_rna_array_cb_index, FALSE); + Py_DECREF(ret); /* the matrix owns now */ + ret= quat_cb; /* return the matrix instead */ + } + break; + default: + break; + } + } +#endif + + return ret; +} + #endif static StructRNA *pyrna_struct_as_srna(PyObject *self); @@ -144,25 +208,64 @@ static int pyrna_prop_compare( BPy_PropertyRNA * a, BPy_PropertyRNA * b ) return (a->prop==b->prop && a->ptr.data==b->ptr.data ) ? 0 : -1; } -/* For some reason python3 needs these :/ */ -static PyObject *pyrna_struct_richcmp(BPy_StructRNA * a, BPy_StructRNA * b, int op) +static PyObject *pyrna_struct_richcmp(PyObject *a, PyObject *b, int op) { - int cmp_result= -1; /* assume false */ - if (BPy_StructRNA_Check(a) && BPy_StructRNA_Check(b)) { - cmp_result= pyrna_struct_compare(a, b); + PyObject *res; + int ok= -1; /* zero is true */ + + if (BPy_StructRNA_Check(a) && BPy_StructRNA_Check(b)) + ok= pyrna_struct_compare((BPy_StructRNA *)a, (BPy_StructRNA *)b); + + 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; } - return Py_CmpToRich(op, cmp_result); + Py_INCREF(res); + return res; } -static PyObject *pyrna_prop_richcmp(BPy_PropertyRNA * a, BPy_PropertyRNA * b, int op) +static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op) { - int cmp_result= -1; /* assume false */ - if (BPy_PropertyRNA_Check(a) && BPy_PropertyRNA_Check(b)) { - cmp_result= pyrna_prop_compare(a, b); + PyObject *res; + int ok= -1; /* zero is true */ + + if (BPy_PropertyRNA_Check(a) && BPy_PropertyRNA_Check(b)) + ok= pyrna_prop_compare((BPy_PropertyRNA *)a, (BPy_PropertyRNA *)b); + + 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; } - return Py_CmpToRich(op, cmp_result); + Py_INCREF(res); + return res; } /*----------------------repr--------------------------------------------*/ @@ -267,61 +370,10 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) { PyObject *ret; int type = RNA_property_type(prop); - int len = RNA_property_array_length(prop); + int len = RNA_property_array_length(ptr, prop); if (len > 0) { - /* resolve the array from a new pytype */ - PyObject *ret = pyrna_prop_CreatePyObject(ptr, prop); - -#ifdef USE_MATHUTILS - - /* return a mathutils vector where possible */ - if(RNA_property_type(prop)==PROP_FLOAT) { - switch(RNA_property_subtype(prop)) { - case PROP_TRANSLATION: - case PROP_DIRECTION: - case PROP_VELOCITY: - case PROP_ACCELERATION: - case PROP_XYZ: - if(len>=2 && len <= 4) { - PyObject *vec_cb= newVectorObject_cb(ret, len, mathutils_rna_array_cb_index, FALSE); - Py_DECREF(ret); /* the vector owns now */ - ret= vec_cb; /* return the vector instead */ - } - break; - case PROP_MATRIX: - if(len==16) { - PyObject *mat_cb= newMatrixObject_cb(ret, 4,4, mathutils_rna_matrix_cb_index, FALSE); - Py_DECREF(ret); /* the matrix owns now */ - ret= mat_cb; /* return the matrix instead */ - } - else if (len==9) { - PyObject *mat_cb= newMatrixObject_cb(ret, 3,3, mathutils_rna_matrix_cb_index, FALSE); - Py_DECREF(ret); /* the matrix owns now */ - ret= mat_cb; /* return the matrix instead */ - } - break; - case PROP_EULER: - case PROP_QUATERNION: - if(len==3) { /* euler */ - PyObject *eul_cb= newEulerObject_cb(ret, mathutils_rna_array_cb_index, FALSE); - Py_DECREF(ret); /* the matrix owns now */ - ret= eul_cb; /* return the matrix instead */ - } - else if (len==4) { - PyObject *quat_cb= newQuaternionObject_cb(ret, mathutils_rna_array_cb_index, FALSE); - Py_DECREF(ret); /* the matrix owns now */ - ret= quat_cb; /* return the matrix instead */ - } - break; - default: - break; - } - } - -#endif - - return ret; + return pyrna_py_from_array(ptr, prop); } /* see if we can coorce into a python type - PropertyType */ @@ -490,128 +542,32 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v { /* XXX hard limits should be checked here */ int type = RNA_property_type(prop); - int len = RNA_property_array_length(prop); + int len = RNA_property_array_length(ptr, prop); if (len > 0) { - PyObject *item; - int py_len = -1; - int i; - + /* char error_str[512]; */ + int ok= 1; #ifdef USE_MATHUTILS if(MatrixObject_Check(value)) { MatrixObject *mat = (MatrixObject*)value; if(!BaseMath_ReadCallback(mat)) return -1; - - py_len = mat->rowSize * mat->colSize; } else /* continue... */ #endif - if (PySequence_Check(value)) { - py_len= (int)PySequence_Length(value); - } - else { + if (!PySequence_Check(value)) { PyErr_Format(PyExc_TypeError, "%.200s RNA array assignment expected a sequence instead of %.200s instance.", error_prefix, Py_TYPE(value)->tp_name); return -1; } /* done getting the length */ - - if (py_len != len) { - PyErr_Format(PyExc_TypeError, "%.200s python sequence length %d did not match the RNA array length %d.", error_prefix, py_len, len); - return -1; - } - - /* for arrays we have a limited number of types */ - switch (type) { - case PROP_BOOLEAN: - { - int *param_arr; - if(data) param_arr= (int*)data; - else param_arr= MEM_mallocN(sizeof(int) * len, "pyrna bool array"); - - - /* collect the variables before assigning, incase one of them is incorrect */ - for (i=0; i<len; i++) { - item = PySequence_GetItem(value, i); - param_arr[i] = PyObject_IsTrue( item ); - Py_DECREF(item); - - if (param_arr[i] < 0) { - if(data==NULL) - MEM_freeN(param_arr); - PyErr_Format(PyExc_AttributeError, "%.200s one or more of the values in the sequence is not a boolean", error_prefix); - return -1; - } - } - if(data==NULL) { - RNA_property_boolean_set_array(ptr, prop, param_arr); - MEM_freeN(param_arr); - } - - break; - } - case PROP_INT: - { - int *param_arr; - if(data) param_arr= (int*)data; - else param_arr= MEM_mallocN(sizeof(int) * len, "pyrna int array"); + ok= pyrna_py_to_array(ptr, prop, data, value, error_prefix); - - /* collect the variables */ - for (i=0; i<len; i++) { - item = PySequence_GetItem(value, i); - param_arr[i] = (int)PyLong_AsSsize_t(item); /* deal with any errors later */ - Py_DECREF(item); - } - - if (PyErr_Occurred()) { - if(data==NULL) - MEM_freeN(param_arr); - PyErr_Format(PyExc_AttributeError, "%.200s one or more of the values in the sequence could not be used as an int", error_prefix); - return -1; - } - if(data==NULL) { - RNA_property_int_set_array(ptr, prop, param_arr); - MEM_freeN(param_arr); - } - break; - } - case PROP_FLOAT: - { - float *param_arr; - if(data) param_arr = (float*)data; - else param_arr = MEM_mallocN(sizeof(float) * len, "pyrna float array"); - - -#ifdef USE_MATHUTILS - if(MatrixObject_Check(value) && RNA_property_subtype(prop) == PROP_MATRIX) { - MatrixObject *mat = (MatrixObject*)value; - memcpy(param_arr, mat->contigPtr, sizeof(float) * len); - } else /* continue... */ -#endif - { - /* collect the variables */ - for (i=0; i<len; i++) { - item = PySequence_GetItem(value, i); - param_arr[i] = (float)PyFloat_AsDouble(item); /* deal with any errors later */ - Py_DECREF(item); - } - } - - if (PyErr_Occurred()) { - if(data==NULL) - MEM_freeN(param_arr); - PyErr_Format(PyExc_AttributeError, "%.200s one or more of the values in the sequence could not be used as a float", error_prefix); - return -1; - } - if(data==NULL) { - RNA_property_float_set_array(ptr, prop, param_arr); - MEM_freeN(param_arr); - } - break; - } + if (!ok) { + /* PyErr_Format(PyExc_AttributeError, "%.200s %s", error_prefix, error_str); */ + return -1; } - } else { + } + else { /* Normal Property (not an array) */ /* see if we can coorce into a python type - PropertyType */ @@ -809,82 +765,84 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v return 0; } -static PyObject * pyrna_prop_to_py_index(PointerRNA *ptr, PropertyRNA *prop, int index) +static PyObject * pyrna_prop_to_py_index(BPy_PropertyRNA *self, int index) { - PyObject *ret; - int type = RNA_property_type(prop); - - /* see if we can coorce into a python type - PropertyType */ - switch (type) { - case PROP_BOOLEAN: - ret = PyBool_FromLong( RNA_property_boolean_get_index(ptr, prop, index) ); - break; - case PROP_INT: - ret = PyLong_FromSsize_t( (Py_ssize_t)RNA_property_int_get_index(ptr, prop, index) ); - break; - case PROP_FLOAT: - ret = PyFloat_FromDouble( RNA_property_float_get_index(ptr, prop, index) ); - break; - default: - PyErr_SetString(PyExc_AttributeError, "not an array type"); - ret = NULL; - break; - } - - return ret; + return pyrna_py_from_array_index(self, index); } -static int pyrna_py_to_prop_index(PointerRNA *ptr, PropertyRNA *prop, int index, PyObject *value) +static int pyrna_py_to_prop_index(BPy_PropertyRNA *self, int index, PyObject *value) { int ret = 0; + int totdim; + PointerRNA *ptr= &self->ptr; + PropertyRNA *prop= self->prop; int type = RNA_property_type(prop); - - /* see if we can coorce into a python type - PropertyType */ - switch (type) { - case PROP_BOOLEAN: - { - int param = PyObject_IsTrue( value ); - - if( param < 0 ) { - PyErr_SetString(PyExc_TypeError, "expected True/False or 0/1"); - ret = -1; - } else { - RNA_property_boolean_set_index(ptr, prop, index, param); - } - break; - } - case PROP_INT: - { - int param = PyLong_AsSsize_t(value); - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "expected an int type"); - ret = -1; - } else { - RNA_property_int_set_index(ptr, prop, index, param); + + totdim= RNA_property_array_dimension(ptr, prop, NULL); + + if (totdim > 1) { + /* char error_str[512]; */ + if (!pyrna_py_to_array_index(&self->ptr, self->prop, self->arraydim, self->arrayoffset, index, value, "")) { + /* PyErr_SetString(PyExc_AttributeError, error_str); */ + ret= -1; } - break; } - case PROP_FLOAT: - { - float param = PyFloat_AsDouble(value); - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "expected a float type"); + else { + /* see if we can coorce into a python type - PropertyType */ + switch (type) { + case PROP_BOOLEAN: + { + int param = PyObject_IsTrue( value ); + + if( param < 0 ) { + PyErr_SetString(PyExc_TypeError, "expected True/False or 0/1"); + ret = -1; + } else { + RNA_property_boolean_set_index(ptr, prop, index, param); + } + break; + } + case PROP_INT: + { + int param = PyLong_AsSsize_t(value); + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "expected an int type"); + ret = -1; + } else { + RNA_property_int_set_index(ptr, prop, index, param); + } + break; + } + case PROP_FLOAT: + { + float param = PyFloat_AsDouble(value); + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "expected a float type"); + ret = -1; + } else { + RNA_property_float_set_index(ptr, prop, index, param); + } + break; + } + default: + PyErr_SetString(PyExc_AttributeError, "not an array type"); ret = -1; - } else { - RNA_property_float_set_index(ptr, prop, index, param); + break; } - break; - } - default: - PyErr_SetString(PyExc_AttributeError, "not an array type"); - ret = -1; - break; } return ret; } //---------------sequence------------------------------------------- +static int pyrna_prop_array_length(BPy_PropertyRNA *self) +{ + if (RNA_property_array_dimension(&self->ptr, self->prop, NULL) > 1) + return RNA_property_multi_array_length(&self->ptr, self->prop, self->arraydim); + else + return RNA_property_array_length(&self->ptr, self->prop); +} + static Py_ssize_t pyrna_prop_len( BPy_PropertyRNA * self ) { Py_ssize_t len; @@ -892,10 +850,10 @@ static Py_ssize_t pyrna_prop_len( BPy_PropertyRNA * self ) if (RNA_property_type(self->prop) == PROP_COLLECTION) { len = RNA_property_collection_length(&self->ptr, self->prop); } else { - len = RNA_property_array_length(self->prop); + len = pyrna_prop_array_length(self); if (len==0) { /* not an array*/ - PyErr_SetString(PyExc_AttributeError, "len() only available for collection RNA types"); + PyErr_SetString(PyExc_AttributeError, "len() only available for collection and array RNA types"); return -1; } } @@ -916,14 +874,15 @@ static PyObject *prop_subscript_collection_int(BPy_PropertyRNA * self, int keynu PyErr_Format(PyExc_IndexError, "index %d out of range", keynum); return NULL; } + static PyObject *prop_subscript_array_int(BPy_PropertyRNA * self, int keynum) { - int len= RNA_property_array_length(self->prop); + int len= pyrna_prop_array_length(self); if(keynum < 0) keynum += len; if(keynum >= 0 && keynum < len) - return pyrna_prop_to_py_index(&self->ptr, self->prop, keynum); + return pyrna_prop_to_py_index(self, keynum); PyErr_Format(PyExc_IndexError, "index %d out of range", keynum); return NULL; @@ -970,7 +929,7 @@ static PyObject *prop_subscript_array_slice(BPy_PropertyRNA * self, int start, i start = MIN2(start,stop); /* values are clamped from PySlice_GetIndicesEx */ for(count = start; count < stop; count++) - PyList_SetItem(list, count - start, pyrna_prop_to_py_index(&self->ptr, self->prop, count)); + PyList_SetItem(list, count - start, pyrna_prop_to_py_index(self, count)); return list; } @@ -1023,8 +982,8 @@ static PyObject *prop_subscript_array(BPy_PropertyRNA * self, PyObject *key) return prop_subscript_array_int(self, PyLong_AsSsize_t(key)); } else if (PySlice_Check(key)) { - int len= RNA_property_array_length(self->prop); Py_ssize_t start, stop, step, slicelength; + int len = pyrna_prop_array_length(self); if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0) return NULL; @@ -1050,13 +1009,12 @@ static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key ) { if (RNA_property_type(self->prop) == PROP_COLLECTION) { return prop_subscript_collection(self, key); - } else if (RNA_property_array_length(self->prop)) { /* arrays are currently fixed length, zero length means its not an array */ + } else if (RNA_property_array_length(&self->ptr, self->prop)) { /* zero length means its not an array */ return prop_subscript_array(self, key); - } else { - PyErr_SetString(PyExc_TypeError, "rna type is not an array or a collection"); - return NULL; - } + } + PyErr_SetString(PyExc_TypeError, "rna type is not an array or a collection"); + return NULL; } static int prop_subscript_ass_array_slice(BPy_PropertyRNA * self, int begin, int end, PyObject *value) @@ -1067,7 +1025,7 @@ static int prop_subscript_ass_array_slice(BPy_PropertyRNA * self, int begin, int begin = MIN2(begin,end); for(count = begin; count < end; count++) { - if(pyrna_py_to_prop_index(&self->ptr, self->prop, count - begin, value) == -1) { + if(pyrna_py_to_prop_index(self, count - begin, value) == -1) { /* TODO - this is wrong since some values have been assigned... will need to fix that */ return -1; /* pyrna_struct_CreatePyObject should set the error */ } @@ -1078,13 +1036,12 @@ static int prop_subscript_ass_array_slice(BPy_PropertyRNA * self, int begin, int static int prop_subscript_ass_array_int(BPy_PropertyRNA * self, int keynum, PyObject *value) { - - int len= RNA_property_array_length(self->prop); + int len= pyrna_prop_array_length(self); if(keynum < 0) keynum += len; if(keynum >= 0 && keynum < len) - return pyrna_py_to_prop_index(&self->ptr, self->prop, keynum, value); + return pyrna_py_to_prop_index(self, keynum, value); PyErr_SetString(PyExc_IndexError, "out of range"); return -1; @@ -1113,7 +1070,7 @@ static int pyrna_prop_ass_subscript( BPy_PropertyRNA * self, PyObject *key, PyOb return prop_subscript_ass_array_int(self, i, value); } else if (PySlice_Check(key)) { - int len= RNA_property_array_length(self->prop); + int len= RNA_property_array_length(&self->ptr, self->prop); Py_ssize_t start, stop, step, slicelength; if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0) @@ -1526,7 +1483,7 @@ static void foreach_attr_type( BPy_PropertyRNA *self, char *attr, RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { prop = RNA_struct_find_property(&itemptr, attr); *raw_type= RNA_property_raw_type(prop); - *attr_tot = RNA_property_array_length(prop); + *attr_tot = RNA_property_array_length(&itemptr, prop); *attr_signed= (RNA_property_subtype(prop)==PROP_UNSIGNED) ? FALSE:TRUE; break; } @@ -1565,7 +1522,7 @@ static int foreach_parse_args( if (RNA_property_type(self->prop) == PROP_COLLECTION) array_tot = RNA_property_collection_length(&self->ptr, self->prop); else - array_tot = RNA_property_array_length(self->prop); + array_tot = RNA_property_array_length(&self->ptr, self->prop); target_tot= array_tot * (*attr_tot); @@ -1758,7 +1715,7 @@ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self) if (ret==NULL) { /* collection did not work, try array */ - int len = RNA_property_array_length(self->prop); + int len = pyrna_prop_array_length(self); if (len) { int i; @@ -1766,7 +1723,7 @@ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self) ret = PyList_New(len); for (i=0; i < len; i++) { - PyList_SET_ITEM(ret, i, pyrna_prop_to_py_index(&self->ptr, self->prop, i)); + PyList_SET_ITEM(ret, i, pyrna_prop_to_py_index(self, i)); } } } @@ -1849,7 +1806,7 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) { PyObject *ret; int type = RNA_property_type(prop); - int len = RNA_property_array_length(prop); + int len = RNA_property_array_length(ptr, prop); int a; @@ -1858,7 +1815,7 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) ret = PyTuple_New(len); /* for return values, data is a pointer to an array, not first element pointer */ - if (RNA_property_flag(prop) & PROP_DYNAMIC_ARRAY) + if (RNA_property_flag(prop) & PROP_DYNAMIC) data = *(char**)(char*)data; switch (type) { @@ -2525,6 +2482,9 @@ PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop ) pyrna->ptr = *ptr; pyrna->prop = prop; + + pyrna->arraydim= 0; + pyrna->arrayoffset= 0; return ( PyObject * ) pyrna; } @@ -2689,8 +2649,17 @@ PyObject *BPY_rna_props( void ) static StructRNA *pyrna_struct_as_srna(PyObject *self) { - BPy_StructRNA *py_srna= (BPy_StructRNA*)PyObject_GetAttrString(self, "__rna__"); + BPy_StructRNA *py_srna; StructRNA *srna; + + /* ack, PyObject_GetAttrString wont look up this types tp_dict first :/ */ + if(PyType_Check(self)) { + py_srna = (BPy_StructRNA *)PyDict_GetItemString(((PyTypeObject *)self)->tp_dict, "__rna__"); + Py_XINCREF(py_srna); + } + + if(py_srna==NULL) + py_srna = (BPy_StructRNA*)PyObject_GetAttrString(self, "__rna__"); if(py_srna==NULL) { PyErr_SetString(PyExc_SystemError, "internal error, self had no __rna__ attribute, should never happen."); @@ -2965,12 +2934,12 @@ static StructRNA *pointer_type_from_py(PyObject *value) srna= srna_from_self(value); if(!srna) { - PyErr_SetString(PyExc_SystemError, "expected an RNA type derived from IDPropertyGroup (1)"); + PyErr_SetString(PyExc_SystemError, "expected an RNA type derived from IDPropertyGroup"); return NULL; } if(!RNA_struct_is_a(srna, &RNA_IDPropertyGroup)) { - PyErr_SetString(PyExc_SystemError, "expected an RNA type derived from IDPropertyGroup (3)"); + PyErr_SetString(PyExc_SystemError, "expected an RNA type derived from IDPropertyGroup"); return NULL; } @@ -3047,6 +3016,52 @@ PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw) return NULL; } +static int deferred_register_props(PyObject *py_class, StructRNA *srna) +{ + PyObject *props, *dummy_args, *item; + int i; + + props= PyObject_GetAttrString(py_class, "__props__"); + + if(!props) { + PyErr_Clear(); + return 1; + } + + dummy_args = PyTuple_New(0); + + for(i=0; i<PyList_Size(props); i++) { + PyObject *py_func_ptr, *py_kw, *py_srna_cobject, *py_ret; + item = PyList_GET_ITEM(props, i); + + if(PyArg_ParseTuple(item, "O!O!", &PyCObject_Type, &py_func_ptr, &PyDict_Type, &py_kw)) { + PyObject *(*pyfunc)(PyObject *, PyObject *, PyObject *); + pyfunc = PyCObject_AsVoidPtr(py_func_ptr); + py_srna_cobject = PyCObject_FromVoidPtr(srna, NULL); + + py_ret = pyfunc(py_srna_cobject, dummy_args, py_kw); + Py_DECREF(py_srna_cobject); + + if(py_ret) { + Py_DECREF(py_ret); + } + else { + Py_DECREF(dummy_args); + return 0; + } + } + else { + PyErr_Clear(); + PyErr_SetString(PyExc_AttributeError, "expected list of dicts for __props__."); + Py_DECREF(dummy_args); + return 0; + } + } + + Py_DECREF(dummy_args); + return 1; +} + /*-------------------- Type Registration ------------------------*/ static int rna_function_arg_count(FunctionRNA *func) @@ -3407,6 +3422,9 @@ PyObject *pyrna_basetype_register(PyObject *self, PyObject *py_class) // Py_DECREF(py_class); // shuld be able to do this XXX since the old rna adds a new ref. } + if(!deferred_register_props(py_class, srna_new)) + return NULL; + Py_RETURN_NONE; } @@ -3430,7 +3448,6 @@ PyObject *pyrna_basetype_unregister(PyObject *self, PyObject *py_class) /* get the context, so register callback can do necessary refreshes */ C= BPy_GetContext(); - /* call unregister */ unreg(C, srna); /* calls bpy_class_free, this decref's py_class */ diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 1b8d69bc511..d006b168f45 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -55,6 +55,10 @@ typedef struct { PyObject_HEAD /* required python macro */ PointerRNA ptr; PropertyRNA *prop; + + /* Arystan: this is a hack to allow sub-item r/w access like: face.uv[n][m] */ + int arraydim; /* array dimension, e.g: 0 for face.uv, 2 for face.uv[n][m], etc. */ + int arrayoffset; /* array first item offset, e.g. if face.uv is [4][2], arrayoffset for face.uv[n] is 2n */ } BPy_PropertyRNA; /* cheap trick */ @@ -91,4 +95,12 @@ PyObject *pyrna_basetype_unregister(PyObject *self, PyObject *args); void pyrna_alloc_types(void); void pyrna_free_types(void); +/* primitive type conversion */ +int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix); +int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, int index, PyObject *py, const char *error_prefix); + +PyObject *pyrna_py_from_array(PointerRNA *ptr, PropertyRNA *prop); +PyObject *pyrna_py_from_array_index(BPy_PropertyRNA *self, int index); +PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop); + #endif diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c index 924d1dbf06a..7e35d51bb6d 100644 --- a/source/blender/python/intern/bpy_util.c +++ b/source/blender/python/intern/bpy_util.c @@ -127,44 +127,6 @@ int BPY_flag_from_seq(BPY_flag_def *flagdef, PyObject *seq, int *flag) return 0; /* ok */ } - -/* Copied from pythons 3's Object.c */ -PyObject * -Py_CmpToRich(int op, int cmp) -{ - PyObject *res; - int ok; - - if (PyErr_Occurred()) - return NULL; - switch (op) { - case Py_LT: - ok = cmp < 0; - break; - case Py_LE: - ok = cmp <= 0; - break; - case Py_EQ: - ok = cmp == 0; - break; - case Py_NE: - ok = cmp != 0; - break; - case Py_GT: - ok = cmp > 0; - break; - case Py_GE: - ok = cmp >= 0; - break; - default: - PyErr_BadArgument(); - return NULL; - } - res = ok ? Py_True : Py_False; - Py_INCREF(res); - return res; -} - /* for debugging */ void PyObSpit(char *name, PyObject *var) { fprintf(stderr, "<%s> : ", name); diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h index 0400d595520..83fa7a5b7c4 100644 --- a/source/blender/python/intern/bpy_util.h +++ b/source/blender/python/intern/bpy_util.h @@ -50,8 +50,6 @@ void PyObSpit(char *name, PyObject *var); void PyLineSpit(void); void BPY_getFileAndNum(char **filename, int *lineno); -PyObject *Py_CmpToRich(int op, int cmp); - PyObject *BPY_exception_buffer(void); /* own python like utility function */ |