//----------------------------------mathutils.Quaternion() -------------- static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *seq = NULL; double angle = 0.0f; float quat[QUAT_SIZE] = {0.0f, 0.0f, 0.0f, 0.0f}; if (kwds && PyDict_Size(kwds)) { PyErr_SetString(PyExc_TypeError, "mathutils.Quaternion(): " "takes no keyword args"); return NULL; } if (!PyArg_ParseTuple(args, "|Od:mathutils.Quaternion", &seq, &angle)) return NULL; switch (PyTuple_GET_SIZE(args)) { case 0: break; case 1: if (mathutils_array_parse(quat, QUAT_SIZE, QUAT_SIZE, seq, "mathutils.Quaternion()") == -1) return NULL; break; case 2: if (mathutils_array_parse(quat, 3, 3, seq, "mathutils.Quaternion()") == -1) return NULL; angle = angle_wrap_rad(angle); /* clamp because of precision issues */ axis_angle_to_quat(quat, quat, angle); break; /* PyArg_ParseTuple assures no more then 2 */ } return Quaternion_CreatePyObject(quat, Py_NEW, type); }
static PyObject *Freestyle_blendRamp(PyObject *self, PyObject *args) { PyObject *obj1, *obj2; char *s; int type; float a[3], fac, b[3]; if (!PyArg_ParseTuple(args, "sOfO", &s, &obj1, &fac, &obj2)) return NULL; type = ramp_blend_type(s); if (type < 0) { PyErr_SetString(PyExc_TypeError, "argument 1 is an unknown ramp blend type"); return NULL; } if (mathutils_array_parse(a, 3, 3, obj1, "argument 2 must be a 3D vector " "(either a tuple/list of 3 elements or Vector)") == -1) { return NULL; } if (mathutils_array_parse(b, 3, 3, obj2, "argument 4 must be a 3D vector " "(either a tuple/list of 3 elements or Vector)") == -1) { return NULL; } ramp_blend(type, a, fac, b); return Vector_CreatePyObject(a, 3, Py_NEW, NULL); }
static PyObject *py_kdtree_find(PyKDTree *self, PyObject *args, PyObject *kwargs) { PyObject *py_co; float co[3]; KDTreeNearest nearest; const char *keywords[] = {"co", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O:find", (char **)keywords, &py_co)) { return NULL; } if (mathutils_array_parse(co, 3, 3, py_co, "find: invalid 'co' arg") == -1) return NULL; if (self->count != self->count_balance) { PyErr_SetString(PyExc_RuntimeError, "KDTree must be balanced before calling find()"); return NULL; } nearest.index = -1; BLI_kdtree_find_nearest(self->obj, co, &nearest); return kdtree_nearest_to_py_and_check(&nearest); }
//----------------------------------mathutils.Color() ------------------- //makes a new color for you to play with static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { float col[3]= {0.0f, 0.0f, 0.0f}; if (kwds && PyDict_Size(kwds)) { PyErr_SetString(PyExc_TypeError, "mathutils.Color(): " "takes no keyword args"); return NULL; } switch(PyTuple_GET_SIZE(args)) { case 0: break; case 1: if ((mathutils_array_parse(col, COLOR_SIZE, COLOR_SIZE, PyTuple_GET_ITEM(args, 0), "mathutils.Color()")) == -1) return NULL; break; default: PyErr_SetString(PyExc_TypeError, "mathutils.Color(): " "more then a single arg given"); return NULL; } return Color_CreatePyObject(col, Py_NEW, type); }
/* parse an array of vectors */ int mathutils_array_parse_alloc_v(float **array, int array_dim, 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 != 0) { float *fp; fp = *array = PyMem_Malloc(size * array_dim * sizeof(float)); for (i = 0; i < size; i++, fp += array_dim) { PyObject *item = PySequence_Fast_GET_ITEM(value, i); if (mathutils_array_parse(fp, array_dim, array_dim, item, error_prefix) == -1) { PyMem_Free(*array); *array = NULL; size = -1; break; } } } Py_DECREF(value_fast); return size; }
//----------------------------------mathutils.Euler() ------------------- //makes a new euler for you to play with static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *seq= NULL; const char *order_str= NULL; float eul[EULER_SIZE]= {0.0f, 0.0f, 0.0f}; short order= EULER_ORDER_XYZ; if(kwds && PyDict_Size(kwds)) { PyErr_SetString(PyExc_TypeError, "mathutils.Euler(): takes no keyword args"); return NULL; } if(!PyArg_ParseTuple(args, "|Os:mathutils.Euler", &seq, &order_str)) return NULL; switch(PyTuple_GET_SIZE(args)) { case 0: break; case 2: if((order=euler_order_from_string(order_str, "mathutils.Euler()")) == -1) return NULL; /* intentionally pass through */ case 1: if (mathutils_array_parse(eul, EULER_SIZE, EULER_SIZE, seq, "mathutils.Euler()") == -1) return NULL; break; } return newEulerObject(eul, order, Py_NEW, type); }
static PyObject *py_kdtree_insert(PyKDTree *self, PyObject *args, PyObject *kwargs) { PyObject *py_co; float co[3]; int index; const char *keywords[] = {"co", "index", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "Oi:insert", (char **)keywords, &py_co, &index)) { return NULL; } if (mathutils_array_parse(co, 3, 3, py_co, "insert: invalid 'co' arg") == -1) return NULL; if (index < 0) { PyErr_SetString(PyExc_ValueError, "negative index given"); return NULL; } if (self->count >= self->maxsize) { PyErr_SetString(PyExc_RuntimeError, "Trying to insert more items than KDTree has room for"); return NULL; } BLI_kdtree_insert(self->obj, index, co); self->count++; Py_RETURN_NONE; }
//----------------------------object[z:y]------------------------ //sequence slice (set) static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyObject *seq) { int i, size; float quat[QUAT_SIZE]; if (BaseMath_ReadCallback(self) == -1) return -1; CLAMP(begin, 0, QUAT_SIZE); if (end < 0) end = (QUAT_SIZE + 1) + end; CLAMP(end, 0, QUAT_SIZE); begin = MIN2(begin, end); if ((size = mathutils_array_parse(quat, 0, QUAT_SIZE, seq, "mathutils.Quaternion[begin:end] = []")) == -1) return -1; if (size != (end - begin)) { PyErr_SetString(PyExc_ValueError, "quaternion[begin:end] = []: " "size mismatch in slice assignment"); return -1; } /* parsed well - now set in vector */ for (i = 0; i < size; i++) self->quat[begin + i] = quat[i]; (void)BaseMath_WriteCallback(self); return 0; }
static int Quaternion_axis_vector_set(QuaternionObject *self, PyObject *value, void *UNUSED(closure)) { float tquat[4]; float len; float axis[3]; float angle; if (BaseMath_ReadCallback(self) == -1) return -1; len = normalize_qt_qt(tquat, self->quat); quat_to_axis_angle(axis, &angle, tquat); /* axis value is unused */ if (mathutils_array_parse(axis, 3, 3, value, "quat.axis = other") == -1) return -1; quat__axis_angle_sanitize(axis, &angle); axis_angle_to_quat(self->quat, axis, angle); mul_qt_fl(self->quat, len); if (BaseMath_WriteCallback(self) == -1) return -1; return 0; }
static PyObject *Quaternion_slerp(QuaternionObject *self, PyObject *args) { PyObject *value; float tquat[QUAT_SIZE], quat[QUAT_SIZE], fac; if (!PyArg_ParseTuple(args, "Of:slerp", &value, &fac)) { PyErr_SetString(PyExc_TypeError, "quat.slerp(): " "expected Quaternion types and float"); return NULL; } if (BaseMath_ReadCallback(self) == -1) return NULL; if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "Quaternion.slerp(other), invalid 'other' arg") == -1) { return NULL; } if (fac > 1.0f || fac < 0.0f) { PyErr_SetString(PyExc_ValueError, "quat.slerp(): " "interpolation factor must be between 0.0 and 1.0"); return NULL; } interp_qt_qtqt(quat, self->quat, tquat, fac); return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(self)); }
//----------------------------object[z:y]------------------------ //sequence slice (set) static int Color_ass_slice(ColorObject *self, int begin, int end, PyObject *seq) { int i, size; float col[COLOR_SIZE]; if (BaseMath_ReadCallback(self) == -1) return -1; CLAMP(begin, 0, COLOR_SIZE); if (end<0) end= (COLOR_SIZE + 1) + end; CLAMP(end, 0, COLOR_SIZE); begin = MIN2(begin, end); if ((size=mathutils_array_parse(col, 0, COLOR_SIZE, seq, "mathutils.Color[begin:end] = []")) == -1) return -1; if (size != (end - begin)) { PyErr_SetString(PyExc_ValueError, "color[begin:end] = []: " "size mismatch in slice assignment"); return -1; } for (i= 0; i < COLOR_SIZE; i++) self->col[begin + i] = col[i]; (void)BaseMath_WriteCallback(self); return 0; }
//----------------------------object[z:y]------------------------ //sequence slice (set) static int Euler_ass_slice(EulerObject * self, int begin, int end, PyObject * seq) { int i, size; float eul[EULER_SIZE]; if(!BaseMath_ReadCallback(self)) return -1; CLAMP(begin, 0, EULER_SIZE); if (end<0) end= (EULER_SIZE + 1) + end; CLAMP(end, 0, EULER_SIZE); begin = MIN2(begin,end); if((size=mathutils_array_parse(eul, 0, EULER_SIZE, seq, "mathutils.Euler[begin:end] = []")) == -1) return -1; if(size != (end - begin)){ PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: size mismatch in slice assignment"); return -1; } for(i= 0; i < EULER_SIZE; i++) self->eul[begin + i] = eul[i]; (void)BaseMath_WriteCallback(self); return 0; }
static int bpy_bmloopuv_uv_set(BPy_BMLoopUV *self, PyObject *value, void *UNUSED(closure)) { float tvec[2]; if (mathutils_array_parse(tvec, 2, 2, value, "BMLoopUV.uv") != -1) { copy_v2_v2(self->data->uv, tvec); return 0; } else { return -1; } }
static int bpy_bmvertskin_radius_set(BPy_BMVertSkin *self, PyObject *value, void *UNUSED(closure)) { float tvec[2]; if (mathutils_array_parse(tvec, 2, 2, value, "BMVertSkin.radius") != -1) { copy_v2_v2(self->data->radius, tvec); return 0; } else { return -1; } }
int BPy_BMLoopColor_AssignPyObject(struct MLoopCol *mloopcol, PyObject *value) { float tvec[4]; if (mathutils_array_parse(tvec, 4, 4, value, "BMLoopCol") != -1) { mloopcol_from_float(mloopcol, tvec); return 0; } else { return -1; } }
static int FrsMaterial_emission_set(BPy_FrsMaterial *self, PyObject *value, void *UNUSED(closure)) { float color[4]; if (mathutils_array_parse(color, 4, 4, value, "value must be a 4-dimensional vector") == -1) { return -1; } self->m->setEmission(color[0], color[1], color[2], color[3]); return 0; }
static int StrokeAttribute_color_set(BPy_StrokeAttribute *self, PyObject *value, void *UNUSED(closure)) { float v[3]; if (mathutils_array_parse(v, 3, 3, value, "value must be a 3-dimensional vector") == -1) { return -1; } self->sa->setColor(v[0], v[1], v[2]); return 0; }
static int StrokeAttribute_thickness_set(BPy_StrokeAttribute *self, PyObject *value, void *UNUSED(closure)) { float v[2]; if (mathutils_array_parse(v, 2, 2, value, "value must be a 2-dimensional vector") == -1) { return -1; } self->sa->setThickness(v[0], v[1]); return 0; }
static int SVertex_point_2d_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure)) { float v[3]; if (mathutils_array_parse(v, 3, 3, value, "value must be a 3-dimensional vector") == -1) { return -1; } Vec3r p(v[0], v[1], v[2]); self->sv->setPoint2D(p); return 0; }
static int FEdgeSmooth_normal_set(BPy_FEdgeSmooth *self, PyObject *value, void *UNUSED(closure)) { float v[3]; if (mathutils_array_parse(v, 3, 3, value, "value must be a 3-dimensional vector") == -1) { return -1; } Vec3r p(v[0], v[1], v[2]); self->fes->setNormal(p); return 0; }
static PyObject *Quaternion_dot(QuaternionObject *self, PyObject *value) { float tquat[QUAT_SIZE]; if (BaseMath_ReadCallback(self) == -1) return NULL; if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "Quaternion.dot(other), invalid 'other' arg") == -1) { return NULL; } return PyFloat_FromDouble(dot_qtqt(self->quat, tquat)); }
static PyObject *Quaternion_cross(QuaternionObject *self, PyObject *value) { float quat[QUAT_SIZE], tquat[QUAT_SIZE]; if (BaseMath_ReadCallback(self) == -1) return NULL; if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "Quaternion.cross(other), invalid 'other' arg") == -1) { return NULL; } mul_qt_qtqt(quat, self->quat, tquat); return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(self)); }
static PyObject *Euler_make_compatible(EulerObject * self, PyObject *value) { float teul[EULER_SIZE]; if(!BaseMath_ReadCallback(self)) return NULL; if(mathutils_array_parse(teul, EULER_SIZE, EULER_SIZE, value, "euler.make_compatible(other), invalid 'other' arg") == -1) return NULL; compatible_eul(self->eul, teul); (void)BaseMath_WriteCallback(self); Py_RETURN_NONE; }
static PyObject *Quaternion_rotation_difference(QuaternionObject *self, PyObject *value) { float tquat[QUAT_SIZE], quat[QUAT_SIZE]; if (BaseMath_ReadCallback(self) == -1) return NULL; if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "Quaternion.difference(other), invalid 'other' arg") == -1) { return NULL; } rotation_between_quats_to_quat(quat, self->quat, tquat); return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(self)); }
static int Color_hsv_set(ColorObject *self, PyObject *value, void *UNUSED(closure)) { 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_v(hsv, self->col); if (BaseMath_WriteCallback(self) == -1) return -1; return 0; }
static PyObject *py_kdtree_find_range(PyKDTree *self, PyObject *args, PyObject *kwargs) { PyObject *py_list; PyObject *py_co; float co[3]; KDTreeNearest *nearest = NULL; float radius; int i, found; const char *keywords[] = {"co", "radius", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "Of:find_range", (char **)keywords, &py_co, &radius)) { return NULL; } if (mathutils_array_parse(co, 3, 3, py_co, "find_range: invalid 'co' arg") == -1) return NULL; if (radius < 0.0f) { PyErr_SetString(PyExc_RuntimeError, "negative radius given"); return NULL; } if (self->count != self->count_balance) { PyErr_SetString(PyExc_RuntimeError, "KDTree must be balanced before calling find_range()"); return NULL; } found = BLI_kdtree_range_search(self->obj, co, &nearest, radius); py_list = PyList_New(found); for (i = 0; i < found; i++) { PyList_SET_ITEM(py_list, i, kdtree_nearest_to_py(&nearest[i])); } if (nearest) { MEM_freeN(nearest); } return py_list; }
static PyObject *py_kdtree_find_n(PyKDTree *self, PyObject *args, PyObject *kwargs) { PyObject *py_list; PyObject *py_co; float co[3]; KDTreeNearest *nearest; unsigned int n; int i, found; const char *keywords[] = {"co", "n", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "OI:find_n", (char **)keywords, &py_co, &n)) { return NULL; } if (mathutils_array_parse(co, 3, 3, py_co, "find_n: invalid 'co' arg") == -1) return NULL; if (UINT_IS_NEG(n)) { PyErr_SetString(PyExc_RuntimeError, "negative 'n' given"); return NULL; } if (self->count != self->count_balance) { PyErr_SetString(PyExc_RuntimeError, "KDTree must be balanced before calling find_n()"); return NULL; } nearest = MEM_mallocN(sizeof(KDTreeNearest) * n, __func__); found = BLI_kdtree_find_nearest_n(self->obj, co, nearest, n); py_list = PyList_New(found); for (i = 0; i < found; i++) { PyList_SET_ITEM(py_list, i, kdtree_nearest_to_py(&nearest[i])); } MEM_freeN(nearest); return py_list; }
static PyObject *bpy_bm_geometry_intersect_face_point(BPy_BMFace *UNUSED(self), PyObject *args) { BPy_BMFace *py_face; PyObject *py_point; float point[3]; bool ret; if (!PyArg_ParseTuple(args, "O!O:intersect_face_point", &BPy_BMFace_Type, &py_face, &py_point)) { return NULL; } BPY_BM_CHECK_OBJ(py_face); if (mathutils_array_parse(point, 3, 3, py_point, "intersect_face_point") == -1) { return NULL; } ret = BM_face_point_inside_test(py_face->f, point); return PyBool_FromLong(ret); }
int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObject *py_value) { int ret = 0; void *value = bpy_bmlayeritem_ptr_get(py_ele, py_layer); if (UNLIKELY(value == NULL)) { return -1; } switch (py_layer->type) { case CD_MDEFORMVERT: { ret = BPy_BMDeformVert_AssignPyObject(value, py_value); break; } case CD_PROP_FLT: case CD_PAINT_MASK: { float tmp_val = PyFloat_AsDouble(py_value); if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) { PyErr_Format(PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name); ret = -1; } else { *(float *)value = tmp_val; } break; } case CD_PROP_INT: { int tmp_val = PyC_Long_AsI32(py_value); if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) { /* error is set */ ret = -1; } else { *(int *)value = tmp_val; } break; } case CD_PROP_STR: { MStringProperty *mstring = value; char *tmp_val; Py_ssize_t tmp_val_len; if (UNLIKELY(PyBytes_AsStringAndSize(py_value, &tmp_val, &tmp_val_len) == -1)) { PyErr_Format(PyExc_TypeError, "expected bytes, not a %.200s", Py_TYPE(py_value)->tp_name); ret = -1; } else { if (tmp_val_len > sizeof(mstring->s)) tmp_val_len = sizeof(mstring->s); memcpy(mstring->s, tmp_val, tmp_val_len); mstring->s_len = tmp_val_len; } break; } case CD_MTEXPOLY: { ret = BPy_BMTexPoly_AssignPyObject(value, py_value); break; } case CD_MLOOPUV: { ret = BPy_BMLoopUV_AssignPyObject(value, py_value); break; } case CD_MLOOPCOL: { ret = BPy_BMLoopColor_AssignPyObject(value, py_value); break; } case CD_SHAPEKEY: { float tmp_val[3]; if (UNLIKELY(mathutils_array_parse(tmp_val, 3, 3, py_value, "BMVert[shape] = value") == -1)) { ret = -1; } else { copy_v3_v3((float *)value, tmp_val); } break; } case CD_BWEIGHT: { float tmp_val = PyFloat_AsDouble(py_value); if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) { PyErr_Format(PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name); ret = -1; } else { *(float *)value = clamp_f(tmp_val, 0.0f, 1.0f); } break; } case CD_CREASE: { float tmp_val = PyFloat_AsDouble(py_value); if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) { PyErr_Format(PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name); ret = -1; } else { *(float *)value = clamp_f(tmp_val, 0.0f, 1.0f); } break; } case CD_MVERT_SKIN: { ret = BPy_BMVertSkin_AssignPyObject(value, py_value); break; } default: { PyErr_SetString(PyExc_AttributeError, "readonly / unsupported type"); ret = -1; break; } } return ret; }
int convert_v2(PyObject *obj, void *v) { return mathutils_array_parse((float *)v, 2, 2, obj, "Error parsing 2D vector"); }