py api
authorCampbell Barton <ideasman42@gmail.com>
Sun, 25 Apr 2010 19:27:59 +0000 (19:27 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 25 Apr 2010 19:27:59 +0000 (19:27 +0000)
- 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.

13 files changed:
release/scripts/io/export_fbx.py
release/scripts/io/import_anim_bvh.py
release/scripts/modules/bpy_types.py
release/scripts/op/add_mesh_torus.py
release/scripts/op/object.py
release/scripts/op/uvcalc_smart_project.py
release/scripts/op/vertexpaint_dirt.py
source/blender/python/generic/mathutils.c
source/blender/python/generic/mathutils.h
source/blender/python/generic/mathutils_color.c
source/blender/python/generic/mathutils_euler.c
source/blender/python/generic/mathutils_quat.c
source/blender/python/generic/mathutils_vector.c

index 3aed242289de6160797065691ab081a1c0abc913..ee92399287f31a3e34b5947735d179dfeb738346 100644 (file)
@@ -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' )
index b1020d14b127753d5dbf35d5255808ddae1851e8..bab692f9daf75fec08c574ee5dcb171fa5df19ef 100644 (file)
@@ -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")
index 6def7dcb41f44e4fc1e5fac5fafdaf668473f539..5f3270506686db42fe2be1906c33c27638e4a81d 100644 (file)
@@ -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
index 183a122f513870e8926f9fa9213d5f3eedb89193..d1989db28321ef940079f6374a858f95b89311aa 100644 (file)
@@ -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])
 
index 0b8970ce7989f0e3fa8ca76eca5a43d00152eeb4..8a11ef7aaf69e8d83c07f7a3652b31b4b1cf0766 100644 (file)
@@ -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
index 230f2863a7ff362879314b0bc20add4caa580685..916940d13845da11e3ee5fa779a5ac0737277673 100644 (file)
@@ -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)
index acbf7660e8cc2c9da7457f218c92adeebb98ace6..c7b7ee71964d66dc8126ac963288a8406d247287 100644 (file)
@@ -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])
index e1e1cd2ae69cb2b7ec8299ff60435e2102686324..a9a682bf99889b9ad52e5c62e2bce70981ca0bd4 100644 (file)
@@ -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)
 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
index f5bbcfcf66608d926aa8b3e2fe0a967f75c0d222..eb6ddf3492e8f84db9e87d5cb8c3a27fd84c8692 100644 (file)
@@ -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 */
index 5b401eb066926821c4b2436e4d7bc86a316b27b1..9d770c0e6fd8854f980bc82078365f40706ac51a 100644 (file)
 //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; i<size; i++) {
-               e = PySequence_GetItem(listObject, i);
-               if (e == NULL) { // Failed to read sequence
-                       Py_DECREF(listObject);
-                       PyErr_SetString(PyExc_RuntimeError, "mathutils.Color(): 3d numeric sequence expected\n");
-                       return NULL;
-               }
-
-               col[i]= (float)PyFloat_AsDouble(e);
-               Py_DECREF(e);
-
-               if(col[i]==-1 && PyErr_Occurred()) { // parsed item is not a number
-                       PyErr_SetString(PyExc_TypeError, "mathutils.Color(): 3d numeric sequence expected\n");
-                       return NULL;
-               }
-       }
-       return newColorObject(col, Py_NEW, NULL);
+       return newColorObject(col, Py_NEW, type);
 }
 
 //-----------------------------METHODS----------------------------
@@ -131,7 +101,7 @@ static PyObject *Color_repr(ColorObject * self)
 
        tuple= Color_ToTupleExt(self, -1);
 
-       ret= PyUnicode_FromFormat("Color%R", tuple);
+       ret= PyUnicode_FromFormat("Color(%R)", tuple);
 
        Py_DECREF(tuple);
        return ret;
@@ -363,6 +333,43 @@ static int Color_setChannelHSV(ColorObject * self, PyObject * value, void * type
        return 0;
 }
 
+/* color channel (HSV), color.h/s/v */
+static PyObject *Color_getHSV(ColorObject * self, void *type)
+{
+       float hsv[3];
+       PyObject *ret;
+
+       if(!BaseMath_ReadCallback(self))
+               return NULL;
+
+       rgb_to_hsv(self->col[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 */
index 5ff932d93d115e37a6fb3124feb2a6448f294d58..2c8dbf419971a2b483b4e1a6c33850cf6a547355 100644 (file)
 //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
-
-       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;
-       }
+       PyObject *seq= NULL;
+       char *order_str= NULL;
+
+       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; i<size; i++) {
-               e = PySequence_GetItem(listObject, i);
-               if (e == NULL) { // Failed to read sequence
-                       Py_DECREF(listObject);
-                       PyErr_SetString(PyExc_RuntimeError, "mathutils.Euler(): 3d numeric sequence expected\n");
+       switch(PyTuple_GET_SIZE(args)) {
+       case 0:
+               break;
+       case 2:
+               if((order=euler_order_from_string(order_str, "mathutils.Euler()")) == -1)
                        return NULL;
-               }
-
-               eul[i]= (float)PyFloat_AsDouble(e);
-               Py_DECREF(e);
-               
-               if(eul[i]==-1 && PyErr_Occurred()) { // parsed item is not a number
-                       PyErr_SetString(PyExc_TypeError, "mathutils.Euler(): 3d numeric sequence expected\n");
+               /* intentionally pass through */
+       case 1:
+               if (mathutils_array_parse(eul, 3, 3, seq, "mathutils.Euler()") == -1)
                        return NULL;
-               }
+               break;
        }
        return newEulerObject(eul, order, Py_NEW, NULL);
 }
@@ -353,7 +331,7 @@ static PyObject *Euler_repr(EulerObject * self)
 
        tuple= Euler_ToTupleExt(self, -1);
 
-       ret= PyUnicode_FromFormat("Euler%R", tuple);
+       ret= PyUnicode_FromFormat("Euler(%R)", tuple);
 
        Py_DECREF(tuple);
        return ret;
index 322dcf31092440ae5a6b6febb0637eb270caef71..b9754f674c422eae82bb033e406dae21df1a384a 100644 (file)
@@ -381,7 +381,7 @@ static PyObject *Quaternion_repr(QuaternionObject * self)
 
        tuple= Quaternion_ToTupleExt(self, -1);
 
-       ret= PyUnicode_FromFormat("Quaternion%R", tuple);
+       ret= PyUnicode_FromFormat("Quaternion(%R)", tuple);
 
        Py_DECREF(tuple);
        return ret;
@@ -743,94 +743,27 @@ static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type )
 //----------------------------------mathutils.Quaternion() --------------
 static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-       PyObject *listObject = NULL, *n, *q;
-       int size, i;
-       float quat[4];
+       PyObject *seq= NULL;
        double angle = 0.0f;
+       float quat[4]= {0.0f, 0.0f, 0.0f, 0.0f};
 
-       size = PyTuple_GET_SIZE(args);
-       if (size == 1 || size == 2) { //seq?
-               listObject = PyTuple_GET_ITEM(args, 0);
-               if (PySequence_Check(listObject)) {
-                       size = PySequence_Length(listObject);
-                       if ((size == 4 && PySequence_Length(args) !=1) ||
-                               (size == 3 && PySequence_Length(args) !=2) || (size >4 || 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;
-                               }
-
-                               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");
-                       return NULL;
-               }
-       }else{
-               if(size != 4){
-                       PyErr_SetString(PyExc_AttributeError, "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;
 
-       for (i=0; i<size; i++) { //parse
-               q = PySequence_GetItem(listObject, i);
-               if (q == NULL) { // Failed to read sequence
-                       PyErr_SetString(PyExc_RuntimeError, "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;
-               }
-
-               quat[i] = PyFloat_AsDouble(q);
-               Py_DECREF(q);
-
-               if (quat[i]==-1 && PyErr_Occurred()) {
-                       PyErr_SetString(PyExc_TypeError, "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;
-               }
-       }
-
-       if(size == 3) //calculate the quat based on axis/angle
                axis_angle_to_quat(quat, quat, angle);
-
+               break;
+       /* PyArg_ParseTuple assures no more then 2 */
+       }
        return newQuaternionObject(quat, Py_NEW, NULL);
 }
 
index b825f3187cd030b952f410ede941021cbe591747..c9e151167de43668eb08167b47accbc7fae109d0 100644 (file)
@@ -47,48 +47,20 @@ static PyObject *Vector_ToTupleExt(VectorObject *self, int ndigits);
 // accepted. Mixed float and int values accepted. Ints are parsed to float 
 static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-       PyObject *listObject = NULL;
-       int size, i;
-       float vec[4], f;
-       PyObject *v;
-
-       size = PyTuple_GET_SIZE(args); /* we know its a tuple because its an arg */
-       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.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
+       float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f};
+       int size= 3; /* default to a 3D vector */
+
+       switch(PyTuple_GET_SIZE(args)) {
+       case 0:
+               break;
+       case 1:
+               if((size=mathutils_array_parse(vec, 2, 4, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1)
                        return NULL;
-               }
-       } else if (size == 0) {
-               //returns a new empty 3d vector
-               return newVectorObject(NULL, 3, Py_NEW, type);
-       } else {
-               listObject = args;
-       }
-
-       if (size<2 || size>4) { // 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<size; i++) {
-               v=PySequence_GetItem(listObject, i);
-               if (v==NULL) { // Failed to read sequence
-                       PyErr_SetString(PyExc_RuntimeError, "mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
-                       return NULL;
-               }
-
-               if((f=PyFloat_AsDouble(v)) == -1 && PyErr_Occurred()) { // parsed item not a number
-                       Py_DECREF(v);
-                       PyErr_SetString(PyExc_TypeError, "mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
-                       return NULL;
-               }
-
-               vec[i]= f;
-               Py_DECREF(v);
-       }
        return newVectorObject(vec, size, Py_NEW, type);
 }
 
@@ -726,7 +698,7 @@ static PyObject *Vector_repr(VectorObject *self)
                return NULL;
 
        tuple= Vector_ToTupleExt(self, -1);
-       ret= PyUnicode_FromFormat("Vector%R", tuple);
+       ret= PyUnicode_FromFormat("Vector(%R)", tuple);
        Py_DECREF(tuple);
        return ret;
 }
@@ -1488,8 +1460,8 @@ static int Vector_setLength(VectorObject *self, PyObject * value )
    in Vector_createSwizzleGetSeter. */
 static PyObject *Vector_getSwizzle(VectorObject *self, void *closure)
 {
-       size_t axisA;
-       size_t axisB;
+       size_t axis_to;
+       size_t axis_from;
        float vec[MAX_DIMENSIONS];
        unsigned int swizzleClosure;
        
@@ -1497,22 +1469,22 @@ static PyObject *Vector_getSwizzle(VectorObject *self, void *closure)
                return NULL;
        
        /* Unpack the axes from the closure into an array. */
-       axisA = 0;
+       axis_to = 0;
        swizzleClosure = GET_INT_FROM_POINTER(closure);
        while (swizzleClosure & SWIZZLE_VALID_AXIS)
        {
-               axisB = swizzleClosure & SWIZZLE_AXIS;
-               if(axisB >= 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;
-                       }
 
-                       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;
-               }
+       if (((scalarVal=PyFloat_AsDouble(value)) == -1 && PyErr_Occurred())==0) {
+               int i;
+               for(i=0; i < MAX_DIMENSIONS; i++)
+                       vec_assign[i]= scalarVal;
 
-               memcpy(self->vec, vecTemp, axisB * sizeof(float));
-               /* continue with BaseMathObject_WriteCallback at the end */
+               size_from= axis_from;
+       }
+       else if((size_from=mathutils_array_parse(vec_assign, 2, 4, value, "mathutils.Vector.**** = swizzle assignment")) == -1) {
+               return -1;
        }
-       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 */
+       if(axis_from != size_from) {
+               PyErr_SetString(PyExc_AttributeError, "Error: vector size does not match swizzle.\n");
+               return -1;
        }
-       else if (((scalarVal=PyFloat_AsDouble(value)) == -1 && PyErr_Occurred())==0)
+
+       /* Copy vector contents onto swizzled axes. */
+       axis_from = 0;
+       swizzleClosure = GET_INT_FROM_POINTER(closure);
+       while (swizzleClosure & SWIZZLE_VALID_AXIS)
        {
-               /* 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." );
-               return -1;
+               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;