move mathutils into its own lib.

This commit is contained in:
2011-07-15 04:01:47 +00:00
parent 5ff9acfd28
commit 3a6158a8bf
28 changed files with 410 additions and 357 deletions

View File

@@ -0,0 +1,52 @@
# ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Contributor(s): Campbell Barton
#
# ***** END GPL LICENSE BLOCK *****
set(INC
.
../../blenlib
../../blenkernel
../../makesdna
../../../../intern/guardedalloc
)
set(INC_SYS
${PYTHON_INCLUDE_DIRS}
)
set(SRC
mathutils.c
mathutils_Color.c
mathutils_Euler.c
mathutils_Matrix.c
mathutils_Quaternion.c
mathutils_Vector.c
mathutils_geometry.c
mathutils.h
mathutils_Color.h
mathutils_Euler.h
mathutils_Matrix.h
mathutils_Quaternion.h
mathutils_Vector.h
mathutils_geometry.h
)
blender_add_lib(bf_python_mathutils "${SRC}" "${INC}" "${INC_SYS}")

View File

@@ -0,0 +1,384 @@
/*
* $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* This is a new part of Blender.
*
* Contributor(s): Joseph Gilbert, Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils.c
* \ingroup pygen
*/
#include <Python.h>
#include "mathutils.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
PyDoc_STRVAR(M_Mathutils_doc,
"This module provides access to matrices, eulers, quaternions and vectors."
);
static int mathutils_array_parse_fast(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
{
PyObject *value_fast= NULL;
PyObject *item;
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((item= PySequence_Fast_GET_ITEM(value_fast, i)))) == -1.0f) && PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError,
"%.200s: sequence index %d expected a number, "
"found '%.200s' type, ",
error_prefix, i, Py_TYPE(item)->tp_name);
Py_DECREF(value_fast);
return -1;
}
} while(i);
Py_XDECREF(value_fast);
return size;
}
/* 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)
{
#if 1 /* approx 6x speedup for mathutils types */
int size;
if( (VectorObject_Check(value) && (size= ((VectorObject *)value)->size)) ||
(EulerObject_Check(value) && (size= 3)) ||
(QuaternionObject_Check(value) && (size= 4)) ||
(ColorObject_Check(value) && (size= 3))
) {
if(BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
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);
}
return -1;
}
memcpy(array, ((BaseMathObject *)value)->data, size * sizeof(float));
return size;
}
else
#endif
{
return mathutils_array_parse_fast(array, array_min, array_max, value, error_prefix);
}
}
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
{
if(EulerObject_Check(value)) {
if(BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
else {
eulO_to_mat3(rmat, ((EulerObject *)value)->eul, ((EulerObject *)value)->order);
return 0;
}
}
else if (QuaternionObject_Check(value)) {
if(BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
else {
float tquat[4];
normalize_qt_qt(tquat, ((QuaternionObject *)value)->quat);
quat_to_mat3(rmat, tquat);
return 0;
}
}
else if (MatrixObject_Check(value)) {
if(BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
else if(((MatrixObject *)value)->col_size < 3 || ((MatrixObject *)value)->row_size < 3) {
PyErr_Format(PyExc_ValueError,
"%.200s: matrix must have minimum 3x3 dimensions",
error_prefix);
return -1;
}
else {
matrix_as_3x3(rmat, (MatrixObject *)value);
normalize_m3(rmat);
return 0;
}
}
else {
PyErr_Format(PyExc_TypeError,
"%.200s: expected a Euler, Quaternion or Matrix type, "
"found %.200s", error_prefix, Py_TYPE(value)->tp_name);
return -1;
}
}
//----------------------------------MATRIX FUNCTIONS--------------------
/* Utility functions */
// LomontRRDCompare4, Ever Faster Float Comparisons by Randy Dillon
#define SIGNMASK(i) (-(int)(((unsigned int)(i))>>31))
int EXPP_FloatsAreEqual(float af, float bf, int maxDiff)
{ // solid, fast routine across all platforms
// with constant time behavior
int ai = *(int *)(&af);
int bi = *(int *)(&bf);
int test = SIGNMASK(ai^bi);
int diff, v1, v2;
assert((0 == test) || (0xFFFFFFFF == test));
diff = (ai ^ (test & 0x7fffffff)) - bi;
v1 = maxDiff + diff;
v2 = maxDiff - diff;
return (v1|v2) >= 0;
}
/*---------------------- EXPP_VectorsAreEqual -------------------------
Builds on EXPP_FloatsAreEqual to test vectors */
int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps)
{
int x;
for (x=0; x< size; x++){
if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0)
return 0;
}
return 1;
}
/* Mathutils Callbacks */
/* for mathutils internal use only, eventually should re-alloc but to start with we only have a few users */
static Mathutils_Callback *mathutils_callbacks[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
int Mathutils_RegisterCallback(Mathutils_Callback *cb)
{
int i;
/* find the first free slot */
for(i= 0; mathutils_callbacks[i]; i++) {
if(mathutils_callbacks[i]==cb) /* already registered? */
return i;
}
mathutils_callbacks[i] = cb;
return i;
}
/* use macros to check for NULL */
int _BaseMathObject_ReadCallback(BaseMathObject *self)
{
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
if(cb->get(self, self->cb_subtype) != -1)
return 0;
if(!PyErr_Occurred()) {
PyErr_Format(PyExc_RuntimeError,
"%s read, user has become invalid",
Py_TYPE(self)->tp_name);
}
return -1;
}
int _BaseMathObject_WriteCallback(BaseMathObject *self)
{
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
if(cb->set(self, self->cb_subtype) != -1)
return 0;
if(!PyErr_Occurred()) {
PyErr_Format(PyExc_RuntimeError,
"%s write, user has become invalid",
Py_TYPE(self)->tp_name);
}
return -1;
}
int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index)
{
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
if(cb->get_index(self, self->cb_subtype, index) != -1)
return 0;
if(!PyErr_Occurred()) {
PyErr_Format(PyExc_RuntimeError,
"%s read index, user has become invalid",
Py_TYPE(self)->tp_name);
}
return -1;
}
int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index)
{
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
if(cb->set_index(self, self->cb_subtype, index) != -1)
return 0;
if(!PyErr_Occurred()) {
PyErr_Format(PyExc_RuntimeError,
"%s write index, user has become invalid",
Py_TYPE(self)->tp_name);
}
return -1;
}
/* BaseMathObject generic functions for all mathutils types */
char BaseMathObject_Owner_doc[] = "The item this is wrapping or None (readonly).";
PyObject *BaseMathObject_getOwner(BaseMathObject *self, void *UNUSED(closure))
{
PyObject *ret= self->cb_user ? self->cb_user : Py_None;
Py_INCREF(ret);
return ret;
}
char BaseMathObject_Wrapped_doc[] = "True when this object wraps external data (readonly).\n\n:type: boolean";
PyObject *BaseMathObject_getWrapped(BaseMathObject *self, void *UNUSED(closure))
{
return PyBool_FromLong((self->wrapped == Py_WRAP) ? 1:0);
}
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
{
Py_VISIT(self->cb_user);
return 0;
}
int BaseMathObject_clear(BaseMathObject *self)
{
Py_CLEAR(self->cb_user);
return 0;
}
void BaseMathObject_dealloc(BaseMathObject *self)
{
/* only free non wrapped */
if(self->wrapped != Py_WRAP) {
PyMem_Free(self->data);
}
if(self->cb_user) {
PyObject_GC_UnTrack(self);
BaseMathObject_clear(self);
}
Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); // breaks subtypes
}
/*----------------------------MODULE INIT-------------------------*/
static struct PyMethodDef M_Mathutils_methods[] = {
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef M_Mathutils_module_def = {
PyModuleDef_HEAD_INIT,
"mathutils", /* m_name */
M_Mathutils_doc, /* m_doc */
0, /* m_size */
M_Mathutils_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
PyMODINIT_FUNC PyInit_mathutils(void)
{
PyObject *submodule;
PyObject *item;
if(PyType_Ready(&vector_Type) < 0)
return NULL;
if(PyType_Ready(&matrix_Type) < 0)
return NULL;
if(PyType_Ready(&euler_Type) < 0)
return NULL;
if(PyType_Ready(&quaternion_Type) < 0)
return NULL;
if(PyType_Ready(&color_Type) < 0)
return NULL;
submodule = PyModule_Create(&M_Mathutils_module_def);
/* each type has its own new() function */
PyModule_AddObject(submodule, "Vector", (PyObject *)&vector_Type);
PyModule_AddObject(submodule, "Matrix", (PyObject *)&matrix_Type);
PyModule_AddObject(submodule, "Euler", (PyObject *)&euler_Type);
PyModule_AddObject(submodule, "Quaternion", (PyObject *)&quaternion_Type);
PyModule_AddObject(submodule, "Color", (PyObject *)&color_Type);
/* submodule */
PyModule_AddObject(submodule, "geometry", (item=PyInit_mathutils_geometry()));
/* XXX, python doesnt do imports with this usefully yet
* 'from mathutils.geometry import PolyFill'
* ...fails without this. */
PyDict_SetItemString(PyThreadState_GET()->interp->modules, "mathutils.geometry", item);
Py_INCREF(item);
mathutils_matrix_vector_cb_index= Mathutils_RegisterCallback(&mathutils_matrix_vector_cb);
return submodule;
}

View File

@@ -0,0 +1,111 @@
/*
* $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* This is a new part of Blender.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils.h
* \ingroup pygen
*/
//Include this file for access to vector, quat, matrix, euler, etc...
#ifndef MATHUTILS_H
#define MATHUTILS_H
/* Can cast different mathutils types to this, use for generic funcs */
extern char BaseMathObject_Wrapped_doc[];
extern char BaseMathObject_Owner_doc[];
#define BASE_MATH_MEMBERS(_data) \
PyObject_VAR_HEAD \
float *_data; /* array of data (alias), wrapped status depends on wrapped status */ \
PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */ \
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ \
unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */ \
unsigned char wrapped; /* wrapped data type? */ \
typedef struct {
BASE_MATH_MEMBERS(data)
} BaseMathObject;
#include "mathutils_Vector.h"
#include "mathutils_Matrix.h"
#include "mathutils_Quaternion.h"
#include "mathutils_Euler.h"
#include "mathutils_Color.h"
#include "mathutils_geometry.h"
PyObject *BaseMathObject_getOwner( BaseMathObject * self, void * );
PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void * );
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg);
int BaseMathObject_clear(BaseMathObject *self);
void BaseMathObject_dealloc(BaseMathObject * self);
PyMODINIT_FUNC PyInit_mathutils(void);
int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);
#define Py_NEW 1
#define Py_WRAP 2
typedef struct Mathutils_Callback Mathutils_Callback;
typedef int (*BaseMathCheckFunc)(BaseMathObject *); /* checks the user is still valid */
typedef int (*BaseMathGetFunc)(BaseMathObject *, int); /* gets the vector from the user */
typedef int (*BaseMathSetFunc)(BaseMathObject *, int); /* sets the users vector values once the vector is modified */
typedef int (*BaseMathGetIndexFunc)(BaseMathObject *, int, int); /* same as above but only for an index */
typedef int (*BaseMathSetIndexFunc)(BaseMathObject *, int, int); /* same as above but only for an index */
struct Mathutils_Callback {
BaseMathCheckFunc check;
BaseMathGetFunc get;
BaseMathSetFunc set;
BaseMathGetIndexFunc get_index;
BaseMathSetIndexFunc set_index;
};
int Mathutils_RegisterCallback(Mathutils_Callback *cb);
int _BaseMathObject_ReadCallback(BaseMathObject *self);
int _BaseMathObject_WriteCallback(BaseMathObject *self);
int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index);
int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index);
/* since this is called so often avoid where possible */
#define BaseMath_ReadCallback(_self) (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self):0))
#define BaseMath_WriteCallback(_self) (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self):0))
#define BaseMath_ReadIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index):0))
#define BaseMath_WriteIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index):0))
/* utility func */
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix);
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix);
#endif /* MATHUTILS_H */

View File

@@ -0,0 +1,870 @@
/*
* $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils_Color.c
* \ingroup pygen
*/
#include <Python.h>
#include "mathutils.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#define COLOR_SIZE 3
//----------------------------------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 newColorObject(col, Py_NEW, type);
}
//-----------------------------METHODS----------------------------
/* note: BaseMath_ReadCallback must be called beforehand */
static PyObject *Color_ToTupleExt(ColorObject *self, int ndigits)
{
PyObject *ret;
int i;
ret= PyTuple_New(COLOR_SIZE);
if(ndigits >= 0) {
for(i= 0; i < COLOR_SIZE; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->col[i], ndigits)));
}
}
else {
for(i= 0; i < COLOR_SIZE; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->col[i]));
}
}
return ret;
}
PyDoc_STRVAR(Color_copy_doc,
".. function:: copy()\n"
"\n"
" Returns a copy of this color.\n"
"\n"
" :return: A copy of the color.\n"
" :rtype: :class:`Color`\n"
"\n"
" .. note:: use this to get a copy of a wrapped color with\n"
" no reference to the original data.\n"
);
static PyObject *Color_copy(ColorObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
return newColorObject(self->col, Py_NEW, Py_TYPE(self));
}
//----------------------------print object (internal)--------------
//print the object to screen
static PyObject *Color_repr(ColorObject * self)
{
PyObject *ret, *tuple;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
tuple= Color_ToTupleExt(self, -1);
ret= PyUnicode_FromFormat("Color(%R)", tuple);
Py_DECREF(tuple);
return ret;
}
//------------------------tp_richcmpr
//returns -1 execption, 0 false, 1 true
static PyObject* Color_richcmpr(PyObject *a, PyObject *b, int op)
{
PyObject *res;
int ok= -1; /* zero is true */
if (ColorObject_Check(a) && ColorObject_Check(b)) {
ColorObject *colA= (ColorObject*)a;
ColorObject *colB= (ColorObject*)b;
if(BaseMath_ReadCallback(colA) == -1 || BaseMath_ReadCallback(colB) == -1)
return NULL;
ok= EXPP_VectorsAreEqual(colA->col, colB->col, COLOR_SIZE, 1) ? 0 : -1;
}
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_INCREF(res), res;
}
//---------------------SEQUENCE PROTOCOLS------------------------
//----------------------------len(object)------------------------
//sequence length
static int Color_len(ColorObject *UNUSED(self))
{
return COLOR_SIZE;
}
//----------------------------object[]---------------------------
//sequence accessor (get)
static PyObject *Color_item(ColorObject * self, int i)
{
if(i<0) i= COLOR_SIZE-i;
if(i < 0 || i >= COLOR_SIZE) {
PyErr_SetString(PyExc_IndexError,
"color[attribute]: "
"array index out of range");
return NULL;
}
if(BaseMath_ReadIndexCallback(self, i) == -1)
return NULL;
return PyFloat_FromDouble(self->col[i]);
}
//----------------------------object[]-------------------------
//sequence accessor (set)
static int Color_ass_item(ColorObject * self, int i, PyObject *value)
{
float f = PyFloat_AsDouble(value);
if(f == -1 && PyErr_Occurred()) { // parsed item not a number
PyErr_SetString(PyExc_TypeError,
"color[attribute] = x: "
"argument not a number");
return -1;
}
if(i<0) i= COLOR_SIZE-i;
if(i < 0 || i >= COLOR_SIZE){
PyErr_SetString(PyExc_IndexError, "color[attribute] = x: "
"array assignment index out of range");
return -1;
}
self->col[i] = f;
if(BaseMath_WriteIndexCallback(self, i) == -1)
return -1;
return 0;
}
//----------------------------object[z:y]------------------------
//sequence slice (get)
static PyObject *Color_slice(ColorObject * self, int begin, int end)
{
PyObject *tuple;
int count;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
CLAMP(begin, 0, COLOR_SIZE);
if (end<0) end= (COLOR_SIZE + 1) + end;
CLAMP(end, 0, COLOR_SIZE);
begin= MIN2(begin, end);
tuple= PyTuple_New(end - begin);
for(count= begin; count < end; count++) {
PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->col[count]));
}
return tuple;
}
//----------------------------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;
}
static PyObject *Color_subscript(ColorObject *self, PyObject *item)
{
if (PyIndex_Check(item)) {
Py_ssize_t i;
i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return NULL;
if (i < 0)
i += COLOR_SIZE;
return Color_item(self, i);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0)
return NULL;
if (slicelength <= 0) {
return PyTuple_New(0);
}
else if (step == 1) {
return Color_slice(self, start, stop);
}
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with color");
return NULL;
}
}
else {
PyErr_Format(PyExc_TypeError,
"color indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return NULL;
}
}
static int Color_ass_subscript(ColorObject *self, PyObject *item, PyObject *value)
{
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return -1;
if (i < 0)
i += COLOR_SIZE;
return Color_ass_item(self, i, value);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0)
return -1;
if (step == 1)
return Color_ass_slice(self, start, stop, value);
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with color");
return -1;
}
}
else {
PyErr_Format(PyExc_TypeError,
"color indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return -1;
}
}
//-----------------PROTCOL DECLARATIONS--------------------------
static PySequenceMethods Color_SeqMethods = {
(lenfunc) Color_len, /* sq_length */
(binaryfunc) NULL, /* sq_concat */
(ssizeargfunc) NULL, /* sq_repeat */
(ssizeargfunc) Color_item, /* sq_item */
NULL, /* sq_slice, deprecated */
(ssizeobjargproc) Color_ass_item, /* sq_ass_item */
NULL, /* sq_ass_slice, deprecated */
(objobjproc) NULL, /* sq_contains */
(binaryfunc) NULL, /* sq_inplace_concat */
(ssizeargfunc) NULL, /* sq_inplace_repeat */
};
static PyMappingMethods Color_AsMapping = {
(lenfunc)Color_len,
(binaryfunc)Color_subscript,
(objobjargproc)Color_ass_subscript
};
/* numeric */
/* addition: obj + obj */
static PyObject *Color_add(PyObject *v1, PyObject *v2)
{
ColorObject *color1 = NULL, *color2 = NULL;
float col[COLOR_SIZE];
if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
PyErr_SetString(PyExc_TypeError,
"Color addition: "
"arguments not valid for this operation");
return NULL;
}
color1 = (ColorObject*)v1;
color2 = (ColorObject*)v2;
if(BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
return NULL;
add_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
return newColorObject(col, Py_NEW, Py_TYPE(v1));
}
/* addition in-place: obj += obj */
static PyObject *Color_iadd(PyObject *v1, PyObject *v2)
{
ColorObject *color1 = NULL, *color2 = NULL;
if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
PyErr_SetString(PyExc_TypeError,
"Color addition: "
"arguments not valid for this operation");
return NULL;
}
color1 = (ColorObject*)v1;
color2 = (ColorObject*)v2;
if(BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
return NULL;
add_vn_vn(color1->col, color2->col, COLOR_SIZE);
(void)BaseMath_WriteCallback(color1);
Py_INCREF(v1);
return v1;
}
/* subtraction: obj - obj */
static PyObject *Color_sub(PyObject *v1, PyObject *v2)
{
ColorObject *color1 = NULL, *color2 = NULL;
float col[COLOR_SIZE];
if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
PyErr_SetString(PyExc_TypeError,
"Color subtraction: "
"arguments not valid for this operation");
return NULL;
}
color1 = (ColorObject*)v1;
color2 = (ColorObject*)v2;
if(BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
return NULL;
sub_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
return newColorObject(col, Py_NEW, Py_TYPE(v1));
}
/* subtraction in-place: obj -= obj */
static PyObject *Color_isub(PyObject *v1, PyObject *v2)
{
ColorObject *color1= NULL, *color2= NULL;
if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
PyErr_SetString(PyExc_TypeError,
"Color subtraction: "
"arguments not valid for this operation");
return NULL;
}
color1 = (ColorObject*)v1;
color2 = (ColorObject*)v2;
if(BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
return NULL;
sub_vn_vn(color1->col, color2->col, COLOR_SIZE);
(void)BaseMath_WriteCallback(color1);
Py_INCREF(v1);
return v1;
}
static PyObject *color_mul_float(ColorObject *color, const float scalar)
{
float tcol[COLOR_SIZE];
mul_vn_vn_fl(tcol, color->col, COLOR_SIZE, scalar);
return newColorObject(tcol, Py_NEW, Py_TYPE(color));
}
static PyObject *Color_mul(PyObject *v1, PyObject *v2)
{
ColorObject *color1 = NULL, *color2 = NULL;
float scalar;
if ColorObject_Check(v1) {
color1= (ColorObject *)v1;
if(BaseMath_ReadCallback(color1) == -1)
return NULL;
}
if ColorObject_Check(v2) {
color2= (ColorObject *)v2;
if(BaseMath_ReadCallback(color2) == -1)
return NULL;
}
/* make sure v1 is always the vector */
if (color1 && color2) {
/* col * col, dont support yet! */
}
else if (color1) {
if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* COLOR * FLOAT */
return color_mul_float(color1, scalar);
}
}
else if (color2) {
if (((scalar= PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred())==0) { /* FLOAT * COLOR */
return color_mul_float(color2, scalar);
}
}
else {
BLI_assert(!"internal error");
}
PyErr_Format(PyExc_TypeError,
"Color multiplication: not supported between "
"'%.200s' and '%.200s' types",
Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
return NULL;
}
static PyObject *Color_div(PyObject *v1, PyObject *v2)
{
ColorObject *color1 = NULL;
float scalar;
if ColorObject_Check(v1) {
color1= (ColorObject *)v1;
if(BaseMath_ReadCallback(color1) == -1)
return NULL;
}
else {
PyErr_SetString(PyExc_TypeError,
"Color division not supported in this order");
return NULL;
}
/* make sure v1 is always the vector */
if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* COLOR * FLOAT */
if(scalar==0.0f) {
PyErr_SetString(PyExc_ZeroDivisionError,
"Color division: divide by zero error");
return NULL;
}
return color_mul_float(color1, 1.0f / scalar);
}
PyErr_Format(PyExc_TypeError,
"Color multiplication: not supported between "
"'%.200s' and '%.200s' types",
Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
return NULL;
}
/* mulplication in-place: obj *= obj */
static PyObject *Color_imul(PyObject *v1, PyObject *v2)
{
ColorObject *color = (ColorObject *)v1;
float scalar;
if(BaseMath_ReadCallback(color) == -1)
return NULL;
/* only support color *= float */
if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* COLOR *= FLOAT */
mul_vn_fl(color->col, COLOR_SIZE, scalar);
}
else {
PyErr_SetString(PyExc_TypeError,
"Color multiplication: "
"arguments not acceptable for this operation");
return NULL;
}
(void)BaseMath_WriteCallback(color);
Py_INCREF(v1);
return v1;
}
/* mulplication in-place: obj *= obj */
static PyObject *Color_idiv(PyObject *v1, PyObject *v2)
{
ColorObject *color = (ColorObject *)v1;
float scalar;
if(BaseMath_ReadCallback(color) == -1)
return NULL;
/* only support color /= float */
if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* COLOR /= FLOAT */
if(scalar==0.0f) {
PyErr_SetString(PyExc_ZeroDivisionError,
"Color division: divide by zero error");
return NULL;
}
mul_vn_fl(color->col, COLOR_SIZE, 1.0f / scalar);
}
else {
PyErr_SetString(PyExc_TypeError,
"Color multiplication: "
"arguments not acceptable for this operation");
return NULL;
}
(void)BaseMath_WriteCallback(color);
Py_INCREF(v1);
return v1;
}
/* -obj
returns the negative of this object*/
static PyObject *Color_neg(ColorObject *self)
{
float tcol[COLOR_SIZE];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
negate_vn_vn(tcol, self->col, COLOR_SIZE);
return newColorObject(tcol, Py_NEW, Py_TYPE(self));
}
static PyNumberMethods Color_NumMethods = {
(binaryfunc) Color_add, /*nb_add*/
(binaryfunc) Color_sub, /*nb_subtract*/
(binaryfunc) Color_mul, /*nb_multiply*/
NULL, /*nb_remainder*/
NULL, /*nb_divmod*/
NULL, /*nb_power*/
(unaryfunc) Color_neg, /*nb_negative*/
(unaryfunc) NULL, /*tp_positive*/
(unaryfunc) NULL, /*tp_absolute*/
(inquiry) NULL, /*tp_bool*/
(unaryfunc) NULL, /*nb_invert*/
NULL, /*nb_lshift*/
(binaryfunc)NULL, /*nb_rshift*/
NULL, /*nb_and*/
NULL, /*nb_xor*/
NULL, /*nb_or*/
NULL, /*nb_int*/
NULL, /*nb_reserved*/
NULL, /*nb_float*/
Color_iadd, /* nb_inplace_add */
Color_isub, /* nb_inplace_subtract */
Color_imul, /* nb_inplace_multiply */
NULL, /* nb_inplace_remainder */
NULL, /* nb_inplace_power */
NULL, /* nb_inplace_lshift */
NULL, /* nb_inplace_rshift */
NULL, /* nb_inplace_and */
NULL, /* nb_inplace_xor */
NULL, /* nb_inplace_or */
NULL, /* nb_floor_divide */
Color_div, /* nb_true_divide */
NULL, /* nb_inplace_floor_divide */
Color_idiv, /* nb_inplace_true_divide */
NULL, /* nb_index */
};
/* color channel, vector.r/g/b */
static PyObject *Color_getChannel(ColorObject * self, void *type)
{
return Color_item(self, GET_INT_FROM_POINTER(type));
}
static int Color_setChannel(ColorObject * self, PyObject *value, void * type)
{
return Color_ass_item(self, GET_INT_FROM_POINTER(type), value);
}
/* color channel (HSV), color.h/s/v */
static PyObject *Color_getChannelHSV(ColorObject * self, void *type)
{
float hsv[3];
int i= GET_INT_FROM_POINTER(type);
if(BaseMath_ReadCallback(self) == -1)
return NULL;
rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
return PyFloat_FromDouble(hsv[i]);
}
static int Color_setChannelHSV(ColorObject * self, PyObject *value, void * type)
{
float hsv[3];
int i= GET_INT_FROM_POINTER(type);
float f = PyFloat_AsDouble(value);
if(f == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"color.h/s/v = value: "
"argument not a number");
return -1;
}
if(BaseMath_ReadCallback(self) == -1)
return -1;
rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
CLAMP(f, 0.0f, 1.0f);
hsv[i] = f;
hsv_to_rgb(hsv[0], hsv[1], hsv[2], &(self->col[0]), &(self->col[1]), &(self->col[2]));
if(BaseMath_WriteCallback(self) == -1)
return -1;
return 0;
}
/* color channel (HSV), color.h/s/v */
static PyObject *Color_getHSV(ColorObject * self, void *UNUSED(closure))
{
float hsv[3];
PyObject *ret;
if(BaseMath_ReadCallback(self) == -1)
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 *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(hsv[0], hsv[1], hsv[2], &(self->col[0]), &(self->col[1]), &(self->col[2]));
if(BaseMath_WriteCallback(self) == -1)
return -1;
return 0;
}
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Color_getseters[] = {
{(char *)"r", (getter)Color_getChannel, (setter)Color_setChannel, (char *)"Red color channel.\n\n:type: float", (void *)0},
{(char *)"g", (getter)Color_getChannel, (setter)Color_setChannel, (char *)"Green color channel.\n\n:type: float", (void *)1},
{(char *)"b", (getter)Color_getChannel, (setter)Color_setChannel, (char *)"Blue color channel.\n\n:type: float", (void *)2},
{(char *)"h", (getter)Color_getChannelHSV, (setter)Color_setChannelHSV, (char *)"HSV Hue component in [0, 1].\n\n:type: float", (void *)0},
{(char *)"s", (getter)Color_getChannelHSV, (setter)Color_setChannelHSV, (char *)"HSV Saturation component in [0, 1].\n\n:type: float", (void *)1},
{(char *)"v", (getter)Color_getChannelHSV, (setter)Color_setChannelHSV, (char *)"HSV Value component in [0, 1].\n\n:type: float", (void *)2},
{(char *)"hsv", (getter)Color_getHSV, (setter)Color_setHSV, (char *)"HSV Values in [0, 1].\n\n:type: float triplet", (void *)0},
{(char *)"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
{(char *)"owner", (getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
//-----------------------METHOD DEFINITIONS ----------------------
static struct PyMethodDef Color_methods[] = {
{"__copy__", (PyCFunction) Color_copy, METH_NOARGS, Color_copy_doc},
{"copy", (PyCFunction) Color_copy, METH_NOARGS, Color_copy_doc},
{NULL, NULL, 0, NULL}
};
//------------------PY_OBECT DEFINITION--------------------------
PyDoc_STRVAR(color_doc,
"This object gives access to Colors in Blender."
);
PyTypeObject color_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"mathutils.Color", //tp_name
sizeof(ColorObject), //tp_basicsize
0, //tp_itemsize
(destructor)BaseMathObject_dealloc, //tp_dealloc
NULL, //tp_print
NULL, //tp_getattr
NULL, //tp_setattr
NULL, //tp_compare
(reprfunc) Color_repr, //tp_repr
&Color_NumMethods, //tp_as_number
&Color_SeqMethods, //tp_as_sequence
&Color_AsMapping, //tp_as_mapping
NULL, //tp_hash
NULL, //tp_call
NULL, //tp_str
NULL, //tp_getattro
NULL, //tp_setattro
NULL, //tp_as_buffer
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, //tp_flags
color_doc, //tp_doc
(traverseproc)BaseMathObject_traverse, //tp_traverse
(inquiry)BaseMathObject_clear, //tp_clear
(richcmpfunc)Color_richcmpr, //tp_richcompare
0, //tp_weaklistoffset
NULL, //tp_iter
NULL, //tp_iternext
Color_methods, //tp_methods
NULL, //tp_members
Color_getseters, //tp_getset
NULL, //tp_base
NULL, //tp_dict
NULL, //tp_descr_get
NULL, //tp_descr_set
0, //tp_dictoffset
NULL, //tp_init
NULL, //tp_alloc
Color_new, //tp_new
NULL, //tp_free
NULL, //tp_is_gc
NULL, //tp_bases
NULL, //tp_mro
NULL, //tp_cache
NULL, //tp_subclasses
NULL, //tp_weaklist
NULL //tp_del
};
//------------------------newColorObject (internal)-------------
//creates a new color object
/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
(i.e. it was allocated elsewhere by MEM_mallocN())
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
(i.e. it must be created here with PyMEM_malloc())*/
PyObject *newColorObject(float *col, int type, PyTypeObject *base_type)
{
ColorObject *self;
self= base_type ? (ColorObject *)base_type->tp_alloc(base_type, 0) :
(ColorObject *)PyObject_GC_New(ColorObject, &color_Type);
if(self) {
/* init callbacks as NULL */
self->cb_user= NULL;
self->cb_type= self->cb_subtype= 0;
if(type == Py_WRAP){
self->col = col;
self->wrapped = Py_WRAP;
}
else if (type == Py_NEW){
self->col = PyMem_Malloc(COLOR_SIZE * sizeof(float));
if(col)
copy_v3_v3(self->col, col);
else
zero_v3(self->col);
self->wrapped = Py_NEW;
}
else {
Py_FatalError("Color(): invalid type!");
}
}
return (PyObject *)self;
}
PyObject *newColorObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
{
ColorObject *self= (ColorObject *)newColorObject(NULL, Py_NEW, NULL);
if(self) {
Py_INCREF(cb_user);
self->cb_user= cb_user;
self->cb_type= (unsigned char)cb_type;
self->cb_subtype= (unsigned char)cb_subtype;
PyObject_GC_Track(self);
}
return (PyObject *)self;
}

View File

@@ -0,0 +1,55 @@
/*
* $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/python/generic/mathutils_Color.h
* \ingroup pygen
*/
#ifndef MATHUTILS_COLOR_H
#define MATHUTILS_COLOR_H
extern PyTypeObject color_Type;
#define ColorObject_Check(_v) PyObject_TypeCheck((_v), &color_Type)
typedef struct {
BASE_MATH_MEMBERS(col)
} ColorObject;
/*struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will
be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
//prototypes
PyObject *newColorObject( float *col, int type, PyTypeObject *base_type);
PyObject *newColorObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
#endif /* MATHUTILS_COLOR_H */

View File

@@ -0,0 +1,721 @@
/*
* $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils_Euler.c
* \ingroup pygen
*/
#include <Python.h>
#include "mathutils.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#define EULER_SIZE 3
//----------------------------------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);
}
/* internal use, assuem read callback is done */
static const char *euler_order_str(EulerObject *self)
{
static const char order[][4] = {"XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"};
return order[self->order-EULER_ORDER_XYZ];
}
short euler_order_from_string(const char *str, const char *error_prefix)
{
if((str[0] && str[1] && str[2] && str[3]=='\0')) {
switch(*((PY_INT32_T *)str)) {
case 'X'|'Y'<<8|'Z'<<16: return EULER_ORDER_XYZ;
case 'X'|'Z'<<8|'Y'<<16: return EULER_ORDER_XZY;
case 'Y'|'X'<<8|'Z'<<16: return EULER_ORDER_YXZ;
case 'Y'|'Z'<<8|'X'<<16: return EULER_ORDER_YZX;
case 'Z'|'X'<<8|'Y'<<16: return EULER_ORDER_ZXY;
case 'Z'|'Y'<<8|'X'<<16: return EULER_ORDER_ZYX;
}
}
PyErr_Format(PyExc_ValueError,
"%s: invalid euler order '%s'",
error_prefix, str);
return -1;
}
/* note: BaseMath_ReadCallback must be called beforehand */
static PyObject *Euler_ToTupleExt(EulerObject *self, int ndigits)
{
PyObject *ret;
int i;
ret= PyTuple_New(EULER_SIZE);
if(ndigits >= 0) {
for(i= 0; i < EULER_SIZE; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->eul[i], ndigits)));
}
}
else {
for(i= 0; i < EULER_SIZE; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->eul[i]));
}
}
return ret;
}
//-----------------------------METHODS----------------------------
//return a quaternion representation of the euler
PyDoc_STRVAR(Euler_to_quaternion_doc,
".. method:: to_quaternion()\n"
"\n"
" Return a quaternion representation of the euler.\n"
"\n"
" :return: Quaternion representation of the euler.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Euler_to_quaternion(EulerObject * self)
{
float quat[4];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
eulO_to_quat(quat, self->eul, self->order);
return newQuaternionObject(quat, Py_NEW, NULL);
}
//return a matrix representation of the euler
PyDoc_STRVAR(Euler_to_matrix_doc,
".. method:: to_matrix()\n"
"\n"
" Return a matrix representation of the euler.\n"
"\n"
" :return: A 3x3 roation matrix representation of the euler.\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *Euler_to_matrix(EulerObject * self)
{
float mat[9];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
eulO_to_mat3((float (*)[3])mat, self->eul, self->order);
return newMatrixObject(mat, 3, 3 , Py_NEW, NULL);
}
PyDoc_STRVAR(Euler_zero_doc,
".. method:: zero()\n"
"\n"
" Set all values to zero.\n"
);
static PyObject *Euler_zero(EulerObject * self)
{
zero_v3(self->eul);
if(BaseMath_WriteCallback(self) == -1)
return NULL;
Py_RETURN_NONE;
}
PyDoc_STRVAR(Euler_rotate_axis_doc,
".. method:: rotate_axis(axis, angle)\n"
"\n"
" Rotates the euler a certain amount and returning a unique euler rotation\n"
" (no 720 degree pitches).\n"
"\n"
" :arg axis: single character in ['X, 'Y', 'Z'].\n"
" :type axis: string\n"
" :arg angle: angle in radians.\n"
" :type angle: float\n"
);
static PyObject *Euler_rotate_axis(EulerObject * self, PyObject *args)
{
float angle = 0.0f;
const char *axis;
if(!PyArg_ParseTuple(args, "sf:rotate", &axis, &angle)){
PyErr_SetString(PyExc_TypeError,
"euler.rotate(): "
"expected angle (float) and axis (x, y, z)");
return NULL;
}
if(!(ELEM3(*axis, 'X', 'Y', 'Z') && axis[1]=='\0')){
PyErr_SetString(PyExc_ValueError, "euler.rotate(): "
"expected axis to be 'X', 'Y' or 'Z'");
return NULL;
}
if(BaseMath_ReadCallback(self) == -1)
return NULL;
rotate_eulO(self->eul, self->order, *axis, angle);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Euler_rotate_doc,
".. method:: rotate(other)\n"
"\n"
" Rotates the euler a by another mathutils value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
);
static PyObject *Euler_rotate(EulerObject * self, PyObject *value)
{
float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_any_to_rotmat(other_rmat, value, "euler.rotate(value)") == -1)
return NULL;
eulO_to_mat3(self_rmat, self->eul, self->order);
mul_m3_m3m3(rmat, self_rmat, other_rmat);
mat3_to_compatible_eulO(self->eul, self->eul, self->order, rmat);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Euler_make_compatible_doc,
".. method:: make_compatible(other)\n"
"\n"
" Make this euler compatible with another,\n"
" so interpolating between them works as intended.\n"
"\n"
" .. note:: the rotation order is not taken into account for this function.\n"
);
static PyObject *Euler_make_compatible(EulerObject * self, PyObject *value)
{
float teul[EULER_SIZE];
if(BaseMath_ReadCallback(self) == -1)
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;
}
//----------------------------Euler.rotate()-----------------------
// return a copy of the euler
PyDoc_STRVAR(Euler_copy_doc,
".. function:: copy()\n"
"\n"
" Returns a copy of this euler.\n"
"\n"
" :return: A copy of the euler.\n"
" :rtype: :class:`Euler`\n"
"\n"
" .. note:: use this to get a copy of a wrapped euler with\n"
" no reference to the original data.\n"
);
static PyObject *Euler_copy(EulerObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
return newEulerObject(self->eul, self->order, Py_NEW, Py_TYPE(self));
}
//----------------------------print object (internal)--------------
//print the object to screen
static PyObject *Euler_repr(EulerObject * self)
{
PyObject *ret, *tuple;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
tuple= Euler_ToTupleExt(self, -1);
ret= PyUnicode_FromFormat("Euler(%R, '%s')", tuple, euler_order_str(self));
Py_DECREF(tuple);
return ret;
}
static PyObject* Euler_richcmpr(PyObject *a, PyObject *b, int op)
{
PyObject *res;
int ok= -1; /* zero is true */
if (EulerObject_Check(a) && EulerObject_Check(b)) {
EulerObject *eulA= (EulerObject*)a;
EulerObject *eulB= (EulerObject*)b;
if(BaseMath_ReadCallback(eulA) == -1 || BaseMath_ReadCallback(eulB) == -1)
return NULL;
ok= ((eulA->order == eulB->order) && EXPP_VectorsAreEqual(eulA->eul, eulB->eul, EULER_SIZE, 1)) ? 0 : -1;
}
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_INCREF(res), res;
}
//---------------------SEQUENCE PROTOCOLS------------------------
//----------------------------len(object)------------------------
//sequence length
static int Euler_len(EulerObject *UNUSED(self))
{
return EULER_SIZE;
}
//----------------------------object[]---------------------------
//sequence accessor (get)
static PyObject *Euler_item(EulerObject * self, int i)
{
if(i<0) i= EULER_SIZE-i;
if(i < 0 || i >= EULER_SIZE) {
PyErr_SetString(PyExc_IndexError,
"euler[attribute]: "
"array index out of range");
return NULL;
}
if(BaseMath_ReadIndexCallback(self, i) == -1)
return NULL;
return PyFloat_FromDouble(self->eul[i]);
}
//----------------------------object[]-------------------------
//sequence accessor (set)
static int Euler_ass_item(EulerObject * self, int i, PyObject *value)
{
float f = PyFloat_AsDouble(value);
if(f == -1 && PyErr_Occurred()) { // parsed item not a number
PyErr_SetString(PyExc_TypeError,
"euler[attribute] = x: "
"argument not a number");
return -1;
}
if(i<0) i= EULER_SIZE-i;
if(i < 0 || i >= EULER_SIZE){
PyErr_SetString(PyExc_IndexError,
"euler[attribute] = x: "
"array assignment index out of range");
return -1;
}
self->eul[i] = f;
if(BaseMath_WriteIndexCallback(self, i) == -1)
return -1;
return 0;
}
//----------------------------object[z:y]------------------------
//sequence slice (get)
static PyObject *Euler_slice(EulerObject * self, int begin, int end)
{
PyObject *tuple;
int count;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
CLAMP(begin, 0, EULER_SIZE);
if (end<0) end= (EULER_SIZE + 1) + end;
CLAMP(end, 0, EULER_SIZE);
begin= MIN2(begin, end);
tuple= PyTuple_New(end - begin);
for(count = begin; count < end; count++) {
PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->eul[count]));
}
return tuple;
}
//----------------------------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) == -1)
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_ValueError,
"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 PyObject *Euler_subscript(EulerObject *self, PyObject *item)
{
if (PyIndex_Check(item)) {
Py_ssize_t i;
i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return NULL;
if (i < 0)
i += EULER_SIZE;
return Euler_item(self, i);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
return NULL;
if (slicelength <= 0) {
return PyTuple_New(0);
}
else if (step == 1) {
return Euler_slice(self, start, stop);
}
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with eulers");
return NULL;
}
}
else {
PyErr_Format(PyExc_TypeError,
"euler indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return NULL;
}
}
static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *value)
{
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return -1;
if (i < 0)
i += EULER_SIZE;
return Euler_ass_item(self, i, value);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
return -1;
if (step == 1)
return Euler_ass_slice(self, start, stop, value);
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with euler");
return -1;
}
}
else {
PyErr_Format(PyExc_TypeError,
"euler indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return -1;
}
}
//-----------------PROTCOL DECLARATIONS--------------------------
static PySequenceMethods Euler_SeqMethods = {
(lenfunc) Euler_len, /* sq_length */
(binaryfunc) NULL, /* sq_concat */
(ssizeargfunc) NULL, /* sq_repeat */
(ssizeargfunc) Euler_item, /* sq_item */
(ssizessizeargfunc) NULL, /* sq_slice, deprecated */
(ssizeobjargproc) Euler_ass_item, /* sq_ass_item */
(ssizessizeobjargproc) NULL, /* sq_ass_slice, deprecated */
(objobjproc) NULL, /* sq_contains */
(binaryfunc) NULL, /* sq_inplace_concat */
(ssizeargfunc) NULL, /* sq_inplace_repeat */
};
static PyMappingMethods Euler_AsMapping = {
(lenfunc)Euler_len,
(binaryfunc)Euler_subscript,
(objobjargproc)Euler_ass_subscript
};
/*
* euler axis, euler.x/y/z
*/
static PyObject *Euler_getAxis(EulerObject *self, void *type)
{
return Euler_item(self, GET_INT_FROM_POINTER(type));
}
static int Euler_setAxis(EulerObject *self, PyObject *value, void *type)
{
return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
}
/* rotation order */
static PyObject *Euler_getOrder(EulerObject *self, void *UNUSED(closure))
{
if(BaseMath_ReadCallback(self) == -1) /* can read order too */
return NULL;
return PyUnicode_FromString(euler_order_str(self));
}
static int Euler_setOrder(EulerObject *self, PyObject *value, void *UNUSED(closure))
{
const char *order_str= _PyUnicode_AsString(value);
short order= euler_order_from_string(order_str, "euler.order");
if(order == -1)
return -1;
self->order= order;
(void)BaseMath_WriteCallback(self); /* order can be written back */
return 0;
}
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Euler_getseters[] = {
{(char *)"x", (getter)Euler_getAxis, (setter)Euler_setAxis, (char *)"Euler X axis in radians.\n\n:type: float", (void *)0},
{(char *)"y", (getter)Euler_getAxis, (setter)Euler_setAxis, (char *)"Euler Y axis in radians.\n\n:type: float", (void *)1},
{(char *)"z", (getter)Euler_getAxis, (setter)Euler_setAxis, (char *)"Euler Z axis in radians.\n\n:type: float", (void *)2},
{(char *)"order", (getter)Euler_getOrder, (setter)Euler_setOrder, (char *)"Euler rotation order.\n\n:type: string in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']", (void *)NULL},
{(char *)"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, (char *)BaseMathObject_Wrapped_doc, NULL},
{(char *)"owner", (getter)BaseMathObject_getOwner, (setter)NULL, (char *)BaseMathObject_Owner_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
//-----------------------METHOD DEFINITIONS ----------------------
static struct PyMethodDef Euler_methods[] = {
{"zero", (PyCFunction) Euler_zero, METH_NOARGS, Euler_zero_doc},
{"to_matrix", (PyCFunction) Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc},
{"to_quaternion", (PyCFunction) Euler_to_quaternion, METH_NOARGS, Euler_to_quaternion_doc},
{"rotate_axis", (PyCFunction) Euler_rotate_axis, METH_VARARGS, Euler_rotate_axis_doc},
{"rotate", (PyCFunction) Euler_rotate, METH_O, Euler_rotate_doc},
{"make_compatible", (PyCFunction) Euler_make_compatible, METH_O, Euler_make_compatible_doc},
{"__copy__", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc},
{"copy", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc},
{NULL, NULL, 0, NULL}
};
//------------------PY_OBECT DEFINITION--------------------------
PyDoc_STRVAR(euler_doc,
"This object gives access to Eulers in Blender."
);
PyTypeObject euler_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"mathutils.Euler", //tp_name
sizeof(EulerObject), //tp_basicsize
0, //tp_itemsize
(destructor)BaseMathObject_dealloc, //tp_dealloc
NULL, //tp_print
NULL, //tp_getattr
NULL, //tp_setattr
NULL, //tp_compare
(reprfunc) Euler_repr, //tp_repr
NULL, //tp_as_number
&Euler_SeqMethods, //tp_as_sequence
&Euler_AsMapping, //tp_as_mapping
NULL, //tp_hash
NULL, //tp_call
NULL, //tp_str
NULL, //tp_getattro
NULL, //tp_setattro
NULL, //tp_as_buffer
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, //tp_flags
euler_doc, //tp_doc
(traverseproc)BaseMathObject_traverse, //tp_traverse
(inquiry)BaseMathObject_clear, //tp_clear
(richcmpfunc)Euler_richcmpr, //tp_richcompare
0, //tp_weaklistoffset
NULL, //tp_iter
NULL, //tp_iternext
Euler_methods, //tp_methods
NULL, //tp_members
Euler_getseters, //tp_getset
NULL, //tp_base
NULL, //tp_dict
NULL, //tp_descr_get
NULL, //tp_descr_set
0, //tp_dictoffset
NULL, //tp_init
NULL, //tp_alloc
Euler_new, //tp_new
NULL, //tp_free
NULL, //tp_is_gc
NULL, //tp_bases
NULL, //tp_mro
NULL, //tp_cache
NULL, //tp_subclasses
NULL, //tp_weaklist
NULL //tp_del
};
//------------------------newEulerObject (internal)-------------
//creates a new euler object
/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
(i.e. it was allocated elsewhere by MEM_mallocN())
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
(i.e. it must be created here with PyMEM_malloc())*/
PyObject *newEulerObject(float *eul, short order, int type, PyTypeObject *base_type)
{
EulerObject *self;
self= base_type ? (EulerObject *)base_type->tp_alloc(base_type, 0) :
(EulerObject *)PyObject_GC_New(EulerObject, &euler_Type);
if(self) {
/* init callbacks as NULL */
self->cb_user= NULL;
self->cb_type= self->cb_subtype= 0;
if(type == Py_WRAP) {
self->eul = eul;
self->wrapped = Py_WRAP;
}
else if (type == Py_NEW) {
self->eul = PyMem_Malloc(EULER_SIZE * sizeof(float));
if(eul) {
copy_v3_v3(self->eul, eul);
}
else {
zero_v3(self->eul);
}
self->wrapped = Py_NEW;
}
else {
Py_FatalError("Euler(): invalid type!");
}
self->order= order;
}
return (PyObject *)self;
}
PyObject *newEulerObject_cb(PyObject *cb_user, short order, int cb_type, int cb_subtype)
{
EulerObject *self= (EulerObject *)newEulerObject(NULL, order, Py_NEW, NULL);
if(self) {
Py_INCREF(cb_user);
self->cb_user= cb_user;
self->cb_type= (unsigned char)cb_type;
self->cb_subtype= (unsigned char)cb_subtype;
PyObject_GC_Track(self);
}
return (PyObject *)self;
}

View File

@@ -0,0 +1,60 @@
/*
* $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/python/generic/mathutils_Euler.h
* \ingroup pygen
*/
#ifndef MATHUTILS_EULER_H
#define MATHUTILS_EULER_H
extern PyTypeObject euler_Type;
#define EulerObject_Check(_v) PyObject_TypeCheck((_v), &euler_Type)
typedef struct {
BASE_MATH_MEMBERS(eul)
unsigned char order; /* rotation order */
} EulerObject;
/*struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will
be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
//prototypes
PyObject *newEulerObject( float *eul, short order, int type, PyTypeObject *base_type);
PyObject *newEulerObject_cb(PyObject *cb_user, short order, int cb_type, int cb_subtype);
short euler_order_from_string(const char *str, const char *error_prefix);
#endif /* MATHUTILS_EULER_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
/*
* $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/python/generic/mathutils_Matrix.h
* \ingroup pygen
*/
#ifndef MATHUTILS_MATRIX_H
#define MATHUTILS_MATRIX_H
extern PyTypeObject matrix_Type;
#define MatrixObject_Check(_v) PyObject_TypeCheck((_v), &matrix_Type)
#define MATRIX_MAX_DIM 4
typedef struct {
BASE_MATH_MEMBERS(contigPtr)
float *matrix[MATRIX_MAX_DIM]; /* ptr to the contigPtr (accessor) */
unsigned short row_size;
unsigned short col_size;
} MatrixObject;
/*struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will
be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
/*prototypes*/
PyObject *newMatrixObject(float *mat, const unsigned short row_size, const unsigned short col_size, int type, PyTypeObject *base_type);
PyObject *newMatrixObject_cb(PyObject *user, int row_size, int col_size, int cb_type, int cb_subtype);
extern int mathutils_matrix_vector_cb_index;
extern struct Mathutils_Callback mathutils_matrix_vector_cb;
void matrix_as_3x3(float mat[3][3], MatrixObject *self);
#endif /* MATHUTILS_MATRIX_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
/*
* $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/python/generic/mathutils_Quaternion.h
* \ingroup pygen
*/
#ifndef MATHUTILS_QUAT_H
#define MATHUTILS_QUAT_H
extern PyTypeObject quaternion_Type;
#define QuaternionObject_Check(_v) PyObject_TypeCheck((_v), &quaternion_Type)
typedef struct {
BASE_MATH_MEMBERS(quat)
} QuaternionObject;
/*struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will
be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
//prototypes
PyObject *newQuaternionObject( float *quat, int type, PyTypeObject *base_type);
PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
#endif /* MATHUTILS_QUAT_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
/*
* $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Willian P. Germano & Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/python/generic/mathutils_Vector.h
* \ingroup pygen
*/
#ifndef MATHUTILS_VECTOR_H
#define MATHUTILS_VECTOR_H
extern PyTypeObject vector_Type;
#define VectorObject_Check(_v) PyObject_TypeCheck((_v), &vector_Type)
typedef struct {
BASE_MATH_MEMBERS(vec)
unsigned char size; /* vec size 2,3 or 4 */
} VectorObject;
/*prototypes*/
PyObject *newVectorObject(float *vec, const int size, const int type, PyTypeObject *base_type);
PyObject *newVectorObject_cb(PyObject *user, int size, int callback_type, int subtype);
#endif /* MATHUTILS_VECTOR_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
/*
* $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* This is a new part of Blender.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils_geometry.h
* \ingroup pygen
*/
/*Include this file for access to vector, quat, matrix, euler, etc...*/
#ifndef MATHUTILS_GEOMETRY_H
#define MATHUTILS_GEOMETRY_H
#include "mathutils.h"
PyMODINIT_FUNC PyInit_mathutils_geometry(void);
#endif /* MATHUTILS_GEOMETRY_H */