From 873d4a3f05872bd32f40449a61de5f14e10a2f3d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 25 Apr 2010 19:27:59 +0000 Subject: [PATCH] py api - mathutils.Color.hsv attribute. eg. material.diffuse_color.hsv = 0.2, 0.8, 0.4 - Vector/Euler/Quaternion/Color now only take a single seq arg. - internal function for parsing arrays. (cleanup messy internal list/vector/tuple/seq parsing) - didnt update rigify yet. --- release/scripts/io/export_fbx.py | 71 ++----- release/scripts/io/import_anim_bvh.py | 14 +- release/scripts/modules/bpy_types.py | 8 +- release/scripts/op/add_mesh_torus.py | 4 +- release/scripts/op/object.py | 2 +- release/scripts/op/uvcalc_smart_project.py | 16 +- release/scripts/op/vertexpaint_dirt.py | 2 +- source/blender/python/generic/mathutils.c | 37 ++++ source/blender/python/generic/mathutils.h | 3 + .../blender/python/generic/mathutils_color.c | 91 +++++---- .../blender/python/generic/mathutils_euler.c | 52 ++--- .../blender/python/generic/mathutils_quat.c | 99 ++-------- .../blender/python/generic/mathutils_vector.c | 182 ++++++------------ 13 files changed, 214 insertions(+), 367 deletions(-) diff --git a/release/scripts/io/export_fbx.py b/release/scripts/io/export_fbx.py index 3aed242289d..ee92399287f 100644 --- a/release/scripts/io/export_fbx.py +++ b/release/scripts/io/export_fbx.py @@ -54,50 +54,11 @@ import time import math # math.pi import shutil # for file copying - - - - - - - - - - - - - - - - - - - - - -# import Blender import bpy -import mathutils - - - - - - - - - - - - - - - - - - +from mathutils import Vector, Euler, Matrix, RotationMatrix def copy_file(source, dest): + # XXX - remove, can use shutil file = open(source, 'rb') data = file.read() file.close() @@ -135,7 +96,7 @@ def copy_images(dest_dir, textures): # I guess FBX uses degrees instead of radians (Arystan). # Call this function just before writing to FBX. def eulerRadToDeg(eul): - ret = mathutils.Euler() + ret = Euler() ret.x = 180 / math.pi * eul[0] ret.y = 180 / math.pi * eul[1] @@ -143,10 +104,10 @@ def eulerRadToDeg(eul): return ret -mtx4_identity = mathutils.Matrix() +mtx4_identity = Matrix() # testing -mtx_x90 = mathutils.RotationMatrix( math.pi/2, 3, 'X') # used +mtx_x90 = RotationMatrix( math.pi/2, 3, 'X') # used #mtx_x90n = RotationMatrix(-90, 3, 'x') #mtx_y90 = RotationMatrix( 90, 3, 'y') #mtx_y90n = RotationMatrix(-90, 3, 'y') @@ -154,11 +115,11 @@ mtx_x90 = mathutils.RotationMatrix( math.pi/2, 3, 'X') # used #mtx_z90n = RotationMatrix(-90, 3, 'z') #mtx4_x90 = RotationMatrix( 90, 4, 'x') -mtx4_x90n = mathutils.RotationMatrix(-math.pi/2, 4, 'X') # used +mtx4_x90n = RotationMatrix(-math.pi/2, 4, 'X') # used #mtx4_y90 = RotationMatrix( 90, 4, 'y') -mtx4_y90n = mathutils.RotationMatrix(-math.pi/2, 4, 'Y') # used -mtx4_z90 = mathutils.RotationMatrix( math.pi/2, 4, 'Z') # used -mtx4_z90n = mathutils.RotationMatrix(-math.pi/2, 4, 'Z') # used +mtx4_y90n = RotationMatrix(-math.pi/2, 4, 'Y') # used +mtx4_z90 = RotationMatrix( math.pi/2, 4, 'Z') # used +mtx4_z90n = RotationMatrix(-math.pi/2, 4, 'Z') # used # def strip_path(p): # return p.split('\\')[-1].split('/')[-1] @@ -333,7 +294,7 @@ def write(filename, batch_objects = None, \ EXP_CAMERA = True, EXP_EMPTY = True, EXP_IMAGE_COPY = False, - GLOBAL_MATRIX = mathutils.Matrix(), + GLOBAL_MATRIX = Matrix(), ANIM_ENABLE = True, ANIM_OPTIMIZE = True, ANIM_OPTIMIZE_PRECISSION = 6, @@ -600,8 +561,8 @@ def write(filename, batch_objects = None, \ matrix_rot = matrix_rot * mtx_x90 elif type =='CAMERA': # elif ob and type =='Camera': - y = matrix_rot * mathutils.Vector(0,1,0) - matrix_rot = mathutils.RotationMatrix(math.pi/2, 3, y) * matrix_rot + y = matrix_rot * Vector((0.0, 1.0, 0.0)) + matrix_rot = RotationMatrix(math.pi/2, 3, y) * matrix_rot return matrix_rot @@ -702,8 +663,8 @@ def write(filename, batch_objects = None, \ matrix_rot = matrix_rot * mtx_x90 rot = tuple(matrix_rot.to_euler()) elif ob and ob.type =='Camera': - y = matrix_rot * mathutils.Vector(0,1,0) - matrix_rot = mathutils.RotationMatrix(math.pi/2, 3, y) * matrix_rot + y = matrix_rot * Vector((0.0, 1.0, 0.0)) + matrix_rot = RotationMatrix(math.pi/2, 3, y) * matrix_rot rot = tuple(matrix_rot.to_euler()) else: rot = tuple(matrix_rot.to_euler()) @@ -1088,8 +1049,8 @@ def write(filename, batch_objects = None, \ file.write('\n\t\tTypeFlags: "Camera"') file.write('\n\t\tGeometryVersion: 124') file.write('\n\t\tPosition: %.6f,%.6f,%.6f' % loc) - file.write('\n\t\tUp: %.6f,%.6f,%.6f' % tuple(matrix_rot * mathutils.Vector(0,1,0)) ) - file.write('\n\t\tLookAt: %.6f,%.6f,%.6f' % tuple(matrix_rot * mathutils.Vector(0,0,-1)) ) + file.write('\n\t\tUp: %.6f,%.6f,%.6f' % tuple(matrix_rot * Vector((0.0, 1.0, 0.0)))) + file.write('\n\t\tLookAt: %.6f,%.6f,%.6f' % tuple(matrix_rot * Vector((0.0, 0.0, -1.0)))) #file.write('\n\t\tUp: 0,0,0' ) #file.write('\n\t\tLookAt: 0,0,0' ) diff --git a/release/scripts/io/import_anim_bvh.py b/release/scripts/io/import_anim_bvh.py index b1020d14b12..bab692f9daf 100644 --- a/release/scripts/io/import_anim_bvh.py +++ b/release/scripts/io/import_anim_bvh.py @@ -83,7 +83,7 @@ def eulerRotate(x, y, z, rot_order): # Should work but doesnt! ''' - eul = Euler(x,y,z) + eul = Euler((x, y, z)) eul.order = "XYZ"[rot_order[0]] + "XYZ"[rot_order[1]] + "XYZ"[rot_order[2]] return tuple(eul.to_matrix().to_euler()) ''' @@ -136,7 +136,7 @@ def read_bvh(context, file_path, ROT_MODE='XYZ', GLOBAL_SCALE=1.0): #print '%snode: %s, parent: %s' % (len(bvh_nodes_serial) * ' ', name, bvh_nodes_serial[-1]) lineIdx += 2 # Incriment to the next line (Offset) - rest_head_local = Vector(float(file_lines[lineIdx][1]), float(file_lines[lineIdx][2]), float(file_lines[lineIdx][3])) * GLOBAL_SCALE + rest_head_local = Vector((float(file_lines[lineIdx][1]), float(file_lines[lineIdx][2]), float(file_lines[lineIdx][3]))) * GLOBAL_SCALE lineIdx += 1 # Incriment to the next line (Channels) # newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation] @@ -188,7 +188,7 @@ def read_bvh(context, file_path, ROT_MODE='XYZ', GLOBAL_SCALE=1.0): # Account for an end node if file_lines[lineIdx][0].lower() == 'end' and file_lines[lineIdx][1].lower() == 'site': # There is somtimes a name after 'End Site' but we will ignore it. lineIdx += 2 # Incriment to the next line (Offset) - rest_tail = Vector(float(file_lines[lineIdx][1]), float(file_lines[lineIdx][2]), float(file_lines[lineIdx][3])) * GLOBAL_SCALE + rest_tail = Vector((float(file_lines[lineIdx][1]), float(file_lines[lineIdx][2]), float(file_lines[lineIdx][3]))) * GLOBAL_SCALE bvh_nodes_serial[-1].rest_tail_world = bvh_nodes_serial[-1].rest_head_world + rest_tail bvh_nodes_serial[-1].rest_tail_local = bvh_nodes_serial[-1].rest_head_local + rest_tail @@ -267,8 +267,8 @@ def read_bvh(context, file_path, ROT_MODE='XYZ', GLOBAL_SCALE=1.0): # raise 'error, bvh node has no end and no children. bad file' # Removed temp for now - rest_tail_world = Vector(0.0, 0.0, 0.0) - rest_tail_local = Vector(0.0, 0.0, 0.0) + rest_tail_world = Vector((0.0, 0.0, 0.0)) + rest_tail_local = Vector((0.0, 0.0, 0.0)) for bvh_node_child in bvh_node.children: rest_tail_world += bvh_node_child.rest_head_world rest_tail_local += bvh_node_child.rest_head_local @@ -328,7 +328,7 @@ def bvh_node_dict2objects(context, bvh_nodes, IMPORT_START_FRAME=1, IMPORT_LOOP= lx, ly, lz, rx, ry, rz = bvh_node.anim_data[frame_current] rest_head_local = bvh_node.rest_head_local - bvh_node.temp.loc = rest_head_local + Vector(lx, ly, lz) + bvh_node.temp.loc = rest_head_local + Vector((lx, ly, lz)) bvh_node.temp.rot = rx, ry, rz @@ -531,7 +531,7 @@ def bvh_node_dict2armature(context, bvh_nodes, ROT_MODE='XYZ', IMPORT_START_FRAM prev_euler[i] = euler if bvh_node.has_loc: - pose_bone.location = (bone_rest_matrix_inv * TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local)).translation_part() + pose_bone.location = (bone_rest_matrix_inv * TranslationMatrix(Vector((lx, ly, lz)) - bvh_node.rest_head_local)).translation_part() if bvh_node.has_loc: pose_bone.keyframe_insert("location") diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 6def7dcb41f..5f327050668 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -95,19 +95,19 @@ class _GenericBone: def x_axis(self): """ Vector pointing down the x-axis of the bone. """ - return self.matrix.rotation_part() * Vector(1.0, 0.0, 0.0) + return self.matrix.rotation_part() * Vector((1.0, 0.0, 0.0)) @property def y_axis(self): """ Vector pointing down the x-axis of the bone. """ - return self.matrix.rotation_part() * Vector(0.0, 1.0, 0.0) + return self.matrix.rotation_part() * Vector((0.0, 1.0, 0.0)) @property def z_axis(self): """ Vector pointing down the x-axis of the bone. """ - return self.matrix.rotation_part() * Vector(0.0, 0.0, 1.0) + return self.matrix.rotation_part() * Vector((0.0, 0.0, 1.0)) @property def basename(self): @@ -237,7 +237,7 @@ class EditBone(StructRNA, _GenericBone): Expects a 4x4 or 3x3 matrix. """ from mathutils import Vector - z_vec = self.matrix.rotation_part() * Vector(0.0, 0.0, 1.0) + z_vec = self.matrix.rotation_part() * Vector((0.0, 0.0, 1.0)) self.tail = matrix * self.tail self.head = matrix * self.head scalar = matrix.median_scale diff --git a/release/scripts/op/add_mesh_torus.py b/release/scripts/op/add_mesh_torus.py index 183a122f513..d1989db2832 100644 --- a/release/scripts/op/add_mesh_torus.py +++ b/release/scripts/op/add_mesh_torus.py @@ -39,8 +39,8 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg): for minor_index in range(minor_seg): angle = 2 * pi * minor_index / minor_seg - vec = Vector(major_rad + (cos(angle) * minor_rad), 0.0, - (sin(angle) * minor_rad)) * quat + vec = Vector((major_rad + (cos(angle) * minor_rad), 0.0, + (sin(angle) * minor_rad))) * quat verts.extend([vec.x, vec.y, vec.z]) diff --git a/release/scripts/op/object.py b/release/scripts/op/object.py index 0b8970ce798..8a11ef7aaf6 100644 --- a/release/scripts/op/object.py +++ b/release/scripts/op/object.py @@ -457,7 +457,7 @@ class MakeDupliFace(bpy.types.Operator): SCALE_FAC = 0.01 offset = 0.5 * SCALE_FAC - base_tri = Vector(-offset, -offset, 0.0), Vector(offset, -offset, 0.0), Vector(offset, offset, 0.0), Vector(-offset, offset, 0.0) + base_tri = Vector((-offset, -offset, 0.0)), Vector((offset, -offset, 0.0)), Vector((offset, offset, 0.0)), Vector((-offset, offset, 0.0)) def matrix_to_quat(matrix): # scale = matrix.median_scale diff --git a/release/scripts/op/uvcalc_smart_project.py b/release/scripts/op/uvcalc_smart_project.py index 230f2863a7f..916940d1384 100644 --- a/release/scripts/op/uvcalc_smart_project.py +++ b/release/scripts/op/uvcalc_smart_project.py @@ -199,7 +199,7 @@ def pointInEdges(pt, edges): """ def pointInIsland(pt, island): - vec1 = Vector(); vec2 = Vector(); vec3 = Vector() + vec1, vec2, vec3 = Vector(), Vector(), Vector() for f in island: vec1.x, vec1.y = f.uv[0] vec2.x, vec2.y = f.uv[1] @@ -389,7 +389,7 @@ def mergeUvIslands(islandList): w, h = maxx-minx, maxy-miny totFaceArea = 0 - offset= Vector(minx, miny) + offset= Vector((minx, miny)) for f in islandList[islandIdx]: for uv in f.uv: uv -= offset @@ -513,7 +513,7 @@ def mergeUvIslands(islandList): ##testcount+=1 #print 'Testing intersect' - Intersect = islandIntersectUvIsland(sourceIsland, targetIsland, Vector(boxLeft, boxBottom)) + Intersect = islandIntersectUvIsland(sourceIsland, targetIsland, Vector((boxLeft, boxBottom))) #print 'Done', Intersect if Intersect == 1: # Line intersect, dont bother with this any more pass @@ -539,7 +539,7 @@ def mergeUvIslands(islandList): # Move faces into new island and offset targetIsland[0].extend(sourceIsland[0]) - offset= Vector(boxLeft, boxBottom) + offset= Vector((boxLeft, boxBottom)) for f in sourceIsland[0]: for uv in f.uv: @@ -564,7 +564,7 @@ def mergeUvIslands(islandList): targetIsland[7].extend(sourceIsland[7]) - offset= Vector(boxLeft, boxBottom, 0) + offset= Vector((boxLeft, boxBottom, 0.0)) for p in sourceIsland[7]: p+= offset @@ -780,9 +780,9 @@ def packIslands(islandList): def VectoMat(vec): a3 = vec.__copy__().normalize() - up = Vector(0,0,1) + up = Vector((0.0, 0.0, 1.0)) if abs(a3.dot(up)) == 1.0: - up = Vector(0,1,0) + up = Vector((0.0, 1.0, 0.0)) a1 = a3.cross(up).normalize() a2 = a3.cross(a1) @@ -963,7 +963,7 @@ def main(context, island_margin, projection_limit): newProjectMeshFaces.append(tempMeshFaces.pop(fIdx)) # Add the average of all these faces normals as a projectionVec - averageVec = Vector(0,0,0) + averageVec = Vector(0.0, 0.0, 0.0) if USER_AREA_WEIGHT: for fprop in newProjectMeshFaces: averageVec += (fprop.no * fprop.area) diff --git a/release/scripts/op/vertexpaint_dirt.py b/release/scripts/op/vertexpaint_dirt.py index acbf7660e8c..c7b7ee71964 100644 --- a/release/scripts/op/vertexpaint_dirt.py +++ b/release/scripts/op/vertexpaint_dirt.py @@ -65,7 +65,7 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean, # get the direction of the vectors between the vertex and it's connected vertices for c in con[i]: - vec += Vector(me.verts[c].co - co).normalize() + vec += (me.verts[c].co - co).normalize() # normalize the vector by dividing by the number of connected verts tot_con = len(con[i]) diff --git a/source/blender/python/generic/mathutils.c b/source/blender/python/generic/mathutils.c index e1e1cd2ae69..a9a682bf998 100644 --- a/source/blender/python/generic/mathutils.c +++ b/source/blender/python/generic/mathutils.c @@ -29,6 +29,7 @@ /* Note: Changes to Mathutils since 2.4x * use radians rather then degrees + * - Mathutils.Vector/Euler/Quaternion(), now only take single sequence arguments. * - Mathutils.MidpointVecs --> vector.lerp(other, fac) * - Mathutils.AngleBetweenVecs --> vector.angle(other) * - Mathutils.ProjectVecs --> vector.project(other) @@ -55,6 +56,42 @@ static char M_Mathutils_doc[] = "This module provides access to matrices, eulers, quaternions and vectors."; +/* helper functionm returns length of the 'value', -1 on error */ +int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix) +{ + PyObject *value_fast= NULL; + + int i, size; + + /* non list/tuple cases */ + if(!(value_fast=PySequence_Fast(value, error_prefix))) { + /* PySequence_Fast sets the error */ + return -1; + } + + size= PySequence_Fast_GET_SIZE(value_fast); + + if(size > array_max || size < array_min) { + if (array_max == array_min) PyErr_Format(PyExc_ValueError, "%.200s: sequence size is %d, expected %d", error_prefix, size, array_max); + else PyErr_Format(PyExc_ValueError, "%.200s: sequence size is %d, expected [%d - %d]", error_prefix, size, array_min, array_max); + Py_DECREF(value_fast); + return -1; + } + + i= size; + do { + i--; + if(((array[i]= PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i))) == -1.0) && PyErr_Occurred()) { + PyErr_Format(PyExc_ValueError, "%.200s: sequence index %d is not a float", error_prefix, i); + Py_DECREF(value_fast); + return -1; + } + } while(i); + + Py_XDECREF(value_fast); + return size; +} + //-----------------------------METHODS---------------------------- //-----------------quat_rotation (internal)----------- //This function multiplies a vector/point * quat or vice versa diff --git a/source/blender/python/generic/mathutils.h b/source/blender/python/generic/mathutils.h index f5bbcfcf666..eb6ddf3492e 100644 --- a/source/blender/python/generic/mathutils.h +++ b/source/blender/python/generic/mathutils.h @@ -115,4 +115,7 @@ int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index); #define BaseMath_ReadIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index):1)) #define BaseMath_WriteIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index):1)) +/* utility func */ +int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix); + #endif /* EXPP_Mathutils_H */ diff --git a/source/blender/python/generic/mathutils_color.c b/source/blender/python/generic/mathutils_color.c index 5b401eb0669..9d770c0e6fd 100644 --- a/source/blender/python/generic/mathutils_color.c +++ b/source/blender/python/generic/mathutils_color.c @@ -31,50 +31,20 @@ //makes a new color for you to play with static PyObject *Color_new(PyTypeObject * type, PyObject * args, PyObject * kwargs) { - PyObject *listObject = NULL; - int size, i; - float col[3]; - PyObject *e; + float col[3]= {0.0f, 0.0f, 0.0f}; - - size = PyTuple_GET_SIZE(args); - if (size == 1) { - listObject = PyTuple_GET_ITEM(args, 0); - if (PySequence_Check(listObject)) { - size = PySequence_Length(listObject); - } else { // Single argument was not a sequence - PyErr_SetString(PyExc_TypeError, "mathutils.Color(): 3d numeric sequence expected\n"); + switch(PyTuple_GET_SIZE(args)) { + case 0: + break; + case 1: + if((mathutils_array_parse(col, 3, 3, PyTuple_GET_ITEM(args, 0), "mathutils.Color()")) == -1) return NULL; - } - } else if (size == 0) { - //returns a new empty 3d color - return newColorObject(NULL, Py_NEW, NULL); - } else { - listObject = args; - } - - if (size != 3) { // Invalid color size - PyErr_SetString(PyExc_AttributeError, "mathutils.Color(): 3d numeric sequence expected\n"); + break; + default: + PyErr_SetString(PyExc_TypeError, "mathutils.Color(): more then a single arg given"); return NULL; } - - for (i=0; icol[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2])); + + ret= PyTuple_New(3); + PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(hsv[0])); + PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(hsv[1])); + PyTuple_SET_ITEM(ret, 2, PyFloat_FromDouble(hsv[2])); + return ret; +} + +static int Color_setHSV(ColorObject * self, PyObject * value, void * type) +{ + float hsv[3]; + + if(mathutils_array_parse(hsv, 3, 3, value, "mathutils.Color.hsv = value") == -1) + return -1; + + CLAMP(hsv[0], 0.0f, 1.0f); + CLAMP(hsv[1], 0.0f, 1.0f); + CLAMP(hsv[2], 0.0f, 1.0f); + + hsv_to_rgb(hsv[0], hsv[1], hsv[2], &(self->col[0]), &(self->col[1]), &(self->col[2])); + + if(!BaseMath_WriteCallback(self)) + return -1; + + return 0; +} + /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ @@ -375,6 +382,8 @@ static PyGetSetDef Color_getseters[] = { {"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}, + {"hsv", (getter)Color_getHSV, (setter)Color_setHSV, "HSV Values in [0, 1]. **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}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ diff --git a/source/blender/python/generic/mathutils_euler.c b/source/blender/python/generic/mathutils_euler.c index 5ff932d93d1..2c8dbf41997 100644 --- a/source/blender/python/generic/mathutils_euler.c +++ b/source/blender/python/generic/mathutils_euler.c @@ -39,48 +39,26 @@ //makes a new euler for you to play with static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwargs) { - PyObject *listObject = NULL; - int size, i; - float eul[3]; - PyObject *e; - short order= 0; // TODO, add order option + PyObject *seq= NULL; + char *order_str= NULL; - size = PyTuple_GET_SIZE(args); - if (size == 1) { - listObject = PyTuple_GET_ITEM(args, 0); - if (PySequence_Check(listObject)) { - size = PySequence_Length(listObject); - } else { // Single argument was not a sequence - PyErr_SetString(PyExc_TypeError, "mathutils.Euler(): 3d numeric sequence expected\n"); - return NULL; - } - } else if (size == 0) { - //returns a new empty 3d euler - return newEulerObject(NULL, order, Py_NEW, NULL); - } else { - listObject = args; - } + float eul[3]= {0.0f, 0.0f, 0.0f}; + short order= 0; - if (size != 3) { // Invalid euler size - PyErr_SetString(PyExc_AttributeError, "mathutils.Euler(): 3d numeric sequence expected\n"); + if(!PyArg_ParseTuple(args, "|Os:mathutils.Euler", &seq, &order_str)) return NULL; - } - for (i=0; i4 || size < 3)) { - // invalid args/size - PyErr_SetString(PyExc_AttributeError, "mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n"); - return NULL; - } - if(size == 3){ //get angle in axis/angle - n = PySequence_GetItem(args, 1); - if(n == NULL) { // parsed item not a number or getItem fail - PyErr_SetString(PyExc_TypeError, "mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n"); - return NULL; - } + if(!PyArg_ParseTuple(args, "|Of:mathutils.Quaternion", &seq, &angle)) + return NULL; - angle = PyFloat_AsDouble(n); - Py_DECREF(n); - - if (angle==-1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n"); - return NULL; - } - } - }else{ - listObject = PyTuple_GET_ITEM(args, 1); - if (size>1 && PySequence_Check(listObject)) { - size = PySequence_Length(listObject); - if (size != 3) { - // invalid args/size - PyErr_SetString(PyExc_AttributeError, "mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n"); - return NULL; - } - angle = PyFloat_AsDouble(PyTuple_GET_ITEM(args, 0)); - - if (angle==-1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n"); - return NULL; - } - } else { // argument was not a sequence - PyErr_SetString(PyExc_TypeError, "mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n"); - return NULL; - } - } - } else if (size == 0) { //returns a new empty quat - return newQuaternionObject(NULL, Py_NEW, NULL); - } else { - listObject = args; - } - - if (size == 3) { // invalid quat size - if(PySequence_Length(args) != 2){ - PyErr_SetString(PyExc_AttributeError, "mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n"); + switch(PyTuple_GET_SIZE(args)) { + case 0: + break; + case 1: + if (mathutils_array_parse(quat, 4, 4, seq, "mathutils.Quaternion()") == -1) return NULL; - } - }else{ - if(size != 4){ - PyErr_SetString(PyExc_AttributeError, "mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n"); + break; + case 2: + if (mathutils_array_parse(quat, 3, 3, seq, "mathutils.Quaternion()") == -1) return NULL; - } - } - - for (i=0; i4) { // Invalid vector size - PyErr_SetString(PyExc_AttributeError, "mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n"); + break; + default: + PyErr_SetString(PyExc_TypeError, "mathutils.Vector(): more then a single arg given"); return NULL; } - - for (i=0; i= self->size) { + axis_from = swizzleClosure & SWIZZLE_AXIS; + if(axis_from >= self->size) { PyErr_SetString(PyExc_AttributeError, "Error: vector does not have specified axis."); return NULL; } - vec[axisA] = self->vec[axisB]; + vec[axis_to] = self->vec[axis_from]; swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS; - axisA++; + axis_to++; } - return newVectorObject(vec, axisA, Py_NEW, Py_TYPE(self)); + return newVectorObject(vec, axis_to, Py_NEW, Py_TYPE(self)); } /* Set the items of this vector using a swizzle. @@ -1527,16 +1499,16 @@ static PyObject *Vector_getSwizzle(VectorObject *self, void *closure) unchanged. */ static int Vector_setSwizzle(VectorObject *self, PyObject * value, void *closure) { - VectorObject *vecVal = NULL; - PyObject *item; - size_t listLen; + size_t size_from; float scalarVal; - size_t axisB; - size_t axisA; + size_t axis_from; + size_t axis_to; + unsigned int swizzleClosure; - float vecTemp[MAX_DIMENSIONS]; + float tvec[MAX_DIMENSIONS]; + float vec_assign[MAX_DIMENSIONS]; if(!BaseMath_ReadCallback(self)) return -1; @@ -1544,94 +1516,48 @@ static int Vector_setSwizzle(VectorObject *self, PyObject * value, void *closure /* Check that the closure can be used with this vector: even 2D vectors have swizzles defined for axes z and w, but they would be invalid. */ swizzleClosure = GET_INT_FROM_POINTER(closure); + axis_from= 0; while (swizzleClosure & SWIZZLE_VALID_AXIS) { - axisA = swizzleClosure & SWIZZLE_AXIS; - if (axisA >= self->size) + axis_to = swizzleClosure & SWIZZLE_AXIS; + if (axis_to >= self->size) { PyErr_SetString(PyExc_AttributeError, "Error: vector does not have specified axis.\n"); return -1; } swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS; + axis_from++; } - - if (VectorObject_Check(value)) - { - /* Copy vector contents onto swizzled axes. */ - vecVal = (VectorObject*) value; - axisB = 0; - swizzleClosure = GET_INT_FROM_POINTER(closure); - while (swizzleClosure & SWIZZLE_VALID_AXIS && axisB < vecVal->size) - { - axisA = swizzleClosure & SWIZZLE_AXIS; - if(axisB >= vecVal->size) { - PyErr_SetString(PyExc_AttributeError, "Error: vector does not have specified axis."); - return -1; - } + if (((scalarVal=PyFloat_AsDouble(value)) == -1 && PyErr_Occurred())==0) { + int i; + for(i=0; i < MAX_DIMENSIONS; i++) + vec_assign[i]= scalarVal; - vecTemp[axisA] = vecVal->vec[axisB]; - - swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS; - axisB++; - } - - if(axisB != vecVal->size) { - PyErr_SetString(PyExc_AttributeError, "Error: vector size does not match swizzle.\n"); - return -1; - } - - memcpy(self->vec, vecTemp, axisB * sizeof(float)); - /* continue with BaseMathObject_WriteCallback at the end */ + size_from= axis_from; } - else if (PyList_Check(value)) - { - /* Copy list contents onto swizzled axes. */ - listLen = PyList_GET_SIZE(value); - swizzleClosure = GET_INT_FROM_POINTER(closure); - axisB = 0; - while (swizzleClosure & SWIZZLE_VALID_AXIS && axisB < listLen) - { - item = PyList_GET_ITEM(value, axisB); - - if((scalarVal=PyFloat_AsDouble(item))==-1.0 && PyErr_Occurred()) { - PyErr_SetString(PyExc_AttributeError, "Error: list item could not be used as a float.\n"); - return -1; - } - - - axisA= swizzleClosure & SWIZZLE_AXIS; - vecTemp[axisA] = scalarVal; - - swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS; - axisB++; - } - - if(axisB != listLen) { - PyErr_SetString(PyExc_AttributeError, "Error: list size does not match swizzle.\n"); - return -1; - } - - memcpy(self->vec, vecTemp, axisB * sizeof(float)); - /* continue with BaseMathObject_WriteCallback at the end */ - } - else if (((scalarVal=PyFloat_AsDouble(value)) == -1 && PyErr_Occurred())==0) - { - /* Assign the same value to each axis. */ - swizzleClosure = GET_INT_FROM_POINTER(closure); - while (swizzleClosure & SWIZZLE_VALID_AXIS) - { - axisA = swizzleClosure & SWIZZLE_AXIS; - self->vec[axisA] = scalarVal; - - swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS; - } - /* continue with BaseMathObject_WriteCallback at the end */ - } - else { - PyErr_SetString( PyExc_TypeError, "Expected a Vector, list or scalar value." ); + else if((size_from=mathutils_array_parse(vec_assign, 2, 4, value, "mathutils.Vector.**** = swizzle assignment")) == -1) { return -1; } + + if(axis_from != size_from) { + PyErr_SetString(PyExc_AttributeError, "Error: vector size does not match swizzle.\n"); + return -1; + } + + /* Copy vector contents onto swizzled axes. */ + axis_from = 0; + swizzleClosure = GET_INT_FROM_POINTER(closure); + while (swizzleClosure & SWIZZLE_VALID_AXIS) + { + axis_to = swizzleClosure & SWIZZLE_AXIS; + tvec[axis_to] = vec_assign[axis_from]; + swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS; + axis_from++; + } + + memcpy(self->vec, tvec, axis_from * sizeof(float)); + /* continue with BaseMathObject_WriteCallback at the end */ if(!BaseMath_WriteCallback(self)) return -1;