PyAPI: add utilities PyTuple_SET_ITEMS, Py_INCREF_RET
[blender.git] / source / blender / python / mathutils / mathutils_Euler.c
index a663bd71130e3ac8d536ebda4f5f3ffebcd9ff13..9c0ced39403927ca68d13e68b3137d3e1e4dc00a 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * 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 *****
 
 #include "BLI_math.h"
 #include "BLI_utildefines.h"
-#include "BLI_dynstr.h"
+#include "../generic/python_utildefines.h"
+
+#ifndef MATH_STANDALONE
+#  include "BLI_dynstr.h"
+#endif
 
 #define EULER_SIZE 3
 
-//----------------------------------mathutils.Euler() -------------------
-//makes a new euler for you to play with
+/* ----------------------------------mathutils.Euler() ------------------- */
+/* makes a new euler for you to play with */
 static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
        PyObject *seq = NULL;
@@ -66,13 +65,13 @@ static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
                case 2:
                        if ((order = euler_order_from_string(order_str, "mathutils.Euler()")) == -1)
                                return NULL;
-               /* intentionally pass through */
+                       /* fall-through */
                case 1:
                        if (mathutils_array_parse(eul, EULER_SIZE, EULER_SIZE, seq, "mathutils.Euler()") == -1)
                                return NULL;
                        break;
        }
-       return Euler_CreatePyObject(eul, order, Py_NEW, type);
+       return Euler_CreatePyObject(eul, order, type);
 }
 
 /* internal use, assume read callback is done */
@@ -85,14 +84,23 @@ static const char *euler_order_str(EulerObject *self)
 short euler_order_from_string(const char *str, const char *error_prefix)
 {
        if ((str[0] && str[1] && str[2] && str[3] == '\0')) {
+
+#ifdef __LITTLE_ENDIAN__
+#  define MAKE_ID3(a, b, c)  (((a)) | ((b) << 8) | ((c) << 16))
+#else
+#  define MAKE_ID3(a, b, c)  (((a) << 24) | ((b) << 16) | ((c) << 8))
+#endif
+
                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;
+                       case MAKE_ID3('X', 'Y', 'Z'): return EULER_ORDER_XYZ;
+                       case MAKE_ID3('X', 'Z', 'Y'): return EULER_ORDER_XZY;
+                       case MAKE_ID3('Y', 'X', 'Z'): return EULER_ORDER_YXZ;
+                       case MAKE_ID3('Y', 'Z', 'X'): return EULER_ORDER_YZX;
+                       case MAKE_ID3('Z', 'X', 'Y'): return EULER_ORDER_ZXY;
+                       case MAKE_ID3('Z', 'Y', 'X'): return EULER_ORDER_ZYX;
                }
+
+#undef MAKE_ID3
        }
 
        PyErr_Format(PyExc_ValueError,
@@ -123,8 +131,8 @@ static PyObject *Euler_ToTupleExt(EulerObject *self, int ndigits)
        return ret;
 }
 
-//-----------------------------METHODS----------------------------
-//return a quaternion representation of the euler
+/-----------------------------METHODS----------------------------
+ * return a quaternion representation of the euler */
 
 PyDoc_STRVAR(Euler_to_quaternion_doc,
 ".. method:: to_quaternion()\n"
@@ -143,10 +151,10 @@ static PyObject *Euler_to_quaternion(EulerObject *self)
 
        eulO_to_quat(quat, self->eul, self->order);
 
-       return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
+       return Quaternion_CreatePyObject(quat, NULL);
 }
 
-//return a matrix representation of the euler
+/* return a matrix representation of the euler */
 PyDoc_STRVAR(Euler_to_matrix_doc,
 ".. method:: to_matrix()\n"
 "\n"
@@ -164,7 +172,7 @@ static PyObject *Euler_to_matrix(EulerObject *self)
 
        eulO_to_mat3((float (*)[3])mat, self->eul, self->order);
 
-       return Matrix_CreatePyObject(mat, 3, 3, Py_NEW, NULL);
+       return Matrix_CreatePyObject(mat, 3, 3, NULL);
 }
 
 PyDoc_STRVAR(Euler_zero_doc,
@@ -205,7 +213,7 @@ static PyObject *Euler_rotate_axis(EulerObject *self, PyObject *args)
                return NULL;
        }
 
-       if (!(ELEM3(axis, 'X', 'Y', 'Z'))) {
+       if (!(ELEM(axis, 'X', 'Y', 'Z'))) {
                PyErr_SetString(PyExc_ValueError,
                                "Euler.rotate_axis(): "
                                "expected axis to be 'X', 'Y' or 'Z'");
@@ -226,7 +234,7 @@ static PyObject *Euler_rotate_axis(EulerObject *self, PyObject *args)
 PyDoc_STRVAR(Euler_rotate_doc,
 ".. method:: rotate(other)\n"
 "\n"
-"   Rotates the euler by another mathutils value.\n"
+"   Rotates the euler by another mathutils value.\n"
 "\n"
 "   :arg other: rotation component of mathutils value\n"
 "   :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
@@ -278,8 +286,8 @@ static PyObject *Euler_make_compatible(EulerObject *self, PyObject *value)
        Py_RETURN_NONE;
 }
 
-//----------------------------Euler.rotate()-----------------------
-// return a copy of the euler
+/----------------------------Euler.rotate()-----------------------
+ * return a copy of the euler */
 
 PyDoc_STRVAR(Euler_copy_doc,
 ".. function:: copy()\n"
@@ -297,7 +305,7 @@ static PyObject *Euler_copy(EulerObject *self)
        if (BaseMath_ReadCallback(self) == -1)
                return NULL;
 
-       return Euler_CreatePyObject(self->eul, self->order, Py_NEW, Py_TYPE(self));
+       return Euler_CreatePyObject(self->eul, self->order, Py_TYPE(self));
 }
 static PyObject *Euler_deepcopy(EulerObject *self, PyObject *args)
 {
@@ -306,8 +314,8 @@ static PyObject *Euler_deepcopy(EulerObject *self, PyObject *args)
        return Euler_copy(self);
 }
 
-//----------------------------print object (internal)--------------
-//print the object to screen
+/----------------------------print object (internal)--------------
+ * print the object to screen */
 
 static PyObject *Euler_repr(EulerObject *self)
 {
@@ -324,6 +332,7 @@ static PyObject *Euler_repr(EulerObject *self)
        return ret;
 }
 
+#ifndef MATH_STANDALONE
 static PyObject *Euler_str(EulerObject *self)
 {
        DynStr *ds;
@@ -338,6 +347,7 @@ static PyObject *Euler_str(EulerObject *self)
 
        return mathutils_dynstr_to_py(ds); /* frees ds */
 }
+#endif
 
 static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op)
 {
@@ -356,7 +366,8 @@ static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op)
 
        switch (op) {
                case Py_NE:
-                       ok = !ok; /* pass through */
+                       ok = !ok;
+                       /* fall-through */
                case Py_EQ:
                        res = ok ? Py_False : Py_True;
                        break;
@@ -372,18 +383,18 @@ static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op)
                        return NULL;
        }
 
-       return Py_INCREF(res), res;
+       return Py_INCREF_RET(res);
 }
 
-//---------------------SEQUENCE PROTOCOLS------------------------
-//----------------------------len(object)------------------------
-//sequence length
+/* ---------------------SEQUENCE PROTOCOLS------------------------ */
+/* ----------------------------len(object)------------------------ */
+/* sequence length */
 static int Euler_len(EulerObject *UNUSED(self))
 {
        return EULER_SIZE;
 }
-//----------------------------object[]---------------------------
-//sequence accessor (get)
+/* ----------------------------object[]--------------------------- */
+/* sequence accessor (get) */
 static PyObject *Euler_item(EulerObject *self, int i)
 {
        if (i < 0) i = EULER_SIZE - i;
@@ -401,16 +412,16 @@ static PyObject *Euler_item(EulerObject *self, int i)
        return PyFloat_FromDouble(self->eul[i]);
 
 }
-//----------------------------object[]-------------------------
-//sequence accessor (set)
+/* ----------------------------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
+       if (f == -1 && PyErr_Occurred()) {  /* parsed item not a number */
                PyErr_SetString(PyExc_TypeError,
                                "euler[attribute] = x: "
-                               "argument not a number");
+                               "assigned value not a number");
                return -1;
        }
 
@@ -430,8 +441,8 @@ static int Euler_ass_item(EulerObject *self, int i, PyObject *value)
 
        return 0;
 }
-//----------------------------object[z:y]------------------------
-//sequence slice (get)
+/* ----------------------------object[z:y]------------------------ */
+/* sequence slice (get) */
 static PyObject *Euler_slice(EulerObject *self, int begin, int end)
 {
        PyObject *tuple;
@@ -452,8 +463,8 @@ static PyObject *Euler_slice(EulerObject *self, int begin, int end)
 
        return tuple;
 }
-//----------------------------object[z:y]------------------------
-//sequence slice (set)
+/* ----------------------------object[z:y]------------------------ */
+/* sequence slice (set) */
 static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq)
 {
        int i, size;
@@ -498,7 +509,7 @@ static PyObject *Euler_subscript(EulerObject *self, PyObject *item)
        else if (PySlice_Check(item)) {
                Py_ssize_t start, stop, step, slicelength;
 
-               if (PySlice_GetIndicesEx((void *)item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
+               if (PySlice_GetIndicesEx(item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
                        return NULL;
 
                if (slicelength <= 0) {
@@ -535,7 +546,7 @@ static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *valu
        else if (PySlice_Check(item)) {
                Py_ssize_t start, stop, step, slicelength;
 
-               if (PySlice_GetIndicesEx((void *)item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
+               if (PySlice_GetIndicesEx(item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
                        return -1;
 
                if (step == 1)
@@ -554,7 +565,7 @@ static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *valu
        }
 }
 
-//-----------------PROTCOL DECLARATIONS--------------------------
+/* -----------------PROTCOL DECLARATIONS-------------------------- */
 static PySequenceMethods Euler_SeqMethods = {
        (lenfunc) Euler_len,                    /* sq_length */
        (binaryfunc) NULL,                      /* sq_concat */
@@ -630,7 +641,7 @@ static PyGetSetDef Euler_getseters[] = {
 };
 
 
-//-----------------------METHOD DEFINITIONS ----------------------
+/* -----------------------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},
@@ -644,105 +655,130 @@ static struct PyMethodDef Euler_methods[] = {
        {NULL, NULL, 0, NULL}
 };
 
-//------------------PY_OBECT DEFINITION--------------------------
+/* ------------------PY_OBECT DEFINITION-------------------------- */
 PyDoc_STRVAR(euler_doc,
 "This object gives access to Eulers in Blender."
 );
 PyTypeObject euler_Type = {
        PyVarObject_HEAD_INIT(NULL, 0)
-       "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
-       (reprfunc) Euler_str,           //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
+       "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 */
+#ifndef MATH_STANDALONE
+       (reprfunc) Euler_str,           /* tp_str */
+#else
+       NULL,                           /* tp_str */
+#endif
+       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 */
 };
-//------------------------Euler_CreatePyObject (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 *Euler_CreatePyObject(float *eul, short order, int type, PyTypeObject *base_type)
+
+
+PyObject *Euler_CreatePyObject(
+        const float eul[3], const short order,
+        PyTypeObject *base_type)
 {
        EulerObject *self;
+       float *eul_alloc;
 
-       self = base_type ?  (EulerObject *)base_type->tp_alloc(base_type, 0) :
-                           (EulerObject *)PyObject_GC_New(EulerObject, &euler_Type);
+       eul_alloc = PyMem_Malloc(EULER_SIZE * sizeof(float));
+       if (UNLIKELY(eul_alloc == NULL)) {
+               PyErr_SetString(PyExc_MemoryError,
+                               "Euler(): "
+                               "problem allocating data");
+               return NULL;
+       }
 
+       self = BASE_MATH_NEW(EulerObject, euler_Type, base_type);
        if (self) {
+               self->eul = eul_alloc;
+
                /* 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;
+               if (eul) {
+                       copy_v3_v3(self->eul, eul);
                }
                else {
-                       Py_FatalError("Euler(): invalid type!");
+                       zero_v3(self->eul);
                }
 
+               self->flag = BASE_MATH_FLAG_DEFAULT;
+               self->order = order;
+       }
+       else {
+               PyMem_Free(eul_alloc);
+       }
+
+       return (PyObject *)self;
+}
+
+PyObject *Euler_CreatePyObject_wrap(
+        float eul[3], const short order,
+        PyTypeObject *base_type)
+{
+       EulerObject *self;
+
+       self = BASE_MATH_NEW(EulerObject, euler_Type, base_type);
+       if (self) {
+               /* init callbacks as NULL */
+               self->cb_user = NULL;
+               self->cb_type = self->cb_subtype = 0;
+
+               self->eul = eul;
+               self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP;
+
                self->order = order;
        }
 
        return (PyObject *)self;
 }
 
-PyObject *Euler_CreatePyObject_cb(PyObject *cb_user, short order,
-                                  unsigned char cb_type, unsigned char cb_subtype)
+PyObject *Euler_CreatePyObject_cb(
+        PyObject *cb_user, const short order,
+        unsigned char cb_type, unsigned char cb_subtype)
 {
-       EulerObject *self = (EulerObject *)Euler_CreatePyObject(NULL, order, Py_NEW, NULL);
+       EulerObject *self = (EulerObject *)Euler_CreatePyObject(NULL, order, NULL);
        if (self) {
                Py_INCREF(cb_user);
                self->cb_user         = cb_user;