Blender V2.61 - r43446

mathutils_Color.c

Go to the documentation of this file.
00001 /*
00002  *
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * Contributor(s): Campbell Barton
00020  *
00021  * ***** END GPL LICENSE BLOCK *****
00022  */
00023 
00029 #include <Python.h>
00030 
00031 #include "mathutils.h"
00032 
00033 #include "BLI_math.h"
00034 #include "BLI_utildefines.h"
00035 #include "BLI_dynstr.h"
00036 
00037 #define COLOR_SIZE 3
00038 
00039 //----------------------------------mathutils.Color() -------------------
00040 //makes a new color for you to play with
00041 static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
00042 {
00043     float col[3] = {0.0f, 0.0f, 0.0f};
00044 
00045     if (kwds && PyDict_Size(kwds)) {
00046         PyErr_SetString(PyExc_TypeError,
00047                         "mathutils.Color(): "
00048                         "takes no keyword args");
00049         return NULL;
00050     }
00051 
00052     switch (PyTuple_GET_SIZE(args)) {
00053     case 0:
00054         break;
00055     case 1:
00056         if ((mathutils_array_parse(col, COLOR_SIZE, COLOR_SIZE, PyTuple_GET_ITEM(args, 0), "mathutils.Color()")) == -1)
00057             return NULL;
00058         break;
00059     default:
00060         PyErr_SetString(PyExc_TypeError,
00061                         "mathutils.Color(): "
00062                         "more then a single arg given");
00063         return NULL;
00064     }
00065     return Color_CreatePyObject(col, Py_NEW, type);
00066 }
00067 
00068 //-----------------------------METHODS----------------------------
00069 
00070 /* note: BaseMath_ReadCallback must be called beforehand */
00071 static PyObject *Color_ToTupleExt(ColorObject *self, int ndigits)
00072 {
00073     PyObject *ret;
00074     int i;
00075 
00076     ret = PyTuple_New(COLOR_SIZE);
00077 
00078     if (ndigits >= 0) {
00079         for (i = 0; i < COLOR_SIZE; i++) {
00080             PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->col[i], ndigits)));
00081         }
00082     }
00083     else {
00084         for (i = 0; i < COLOR_SIZE; i++) {
00085             PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->col[i]));
00086         }
00087     }
00088 
00089     return ret;
00090 }
00091 
00092 PyDoc_STRVAR(Color_copy_doc,
00093 ".. function:: copy()\n"
00094 "\n"
00095 "   Returns a copy of this color.\n"
00096 "\n"
00097 "   :return: A copy of the color.\n"
00098 "   :rtype: :class:`Color`\n"
00099 "\n"
00100 "   .. note:: use this to get a copy of a wrapped color with\n"
00101 "      no reference to the original data.\n"
00102 );
00103 static PyObject *Color_copy(ColorObject *self)
00104 {
00105     if (BaseMath_ReadCallback(self) == -1)
00106         return NULL;
00107 
00108     return Color_CreatePyObject(self->col, Py_NEW, Py_TYPE(self));
00109 }
00110 
00111 //----------------------------print object (internal)--------------
00112 //print the object to screen
00113 
00114 static PyObject *Color_repr(ColorObject *self)
00115 {
00116     PyObject *ret, *tuple;
00117 
00118     if (BaseMath_ReadCallback(self) == -1)
00119         return NULL;
00120 
00121     tuple = Color_ToTupleExt(self, -1);
00122 
00123     ret = PyUnicode_FromFormat("Color(%R)", tuple);
00124 
00125     Py_DECREF(tuple);
00126     return ret;
00127 }
00128 
00129 static PyObject *Color_str(ColorObject *self)
00130 {
00131     DynStr *ds;
00132 
00133     if (BaseMath_ReadCallback(self) == -1)
00134         return NULL;
00135 
00136     ds = BLI_dynstr_new();
00137 
00138     BLI_dynstr_appendf(ds, "<Color (r=%.4f, g=%.4f, b=%.4f)>",
00139                        self->col[0], self->col[1], self->col[2]);
00140 
00141     return mathutils_dynstr_to_py(ds); /* frees ds */
00142 }
00143 
00144 //------------------------tp_richcmpr
00145 //returns -1 execption, 0 false, 1 true
00146 static PyObject *Color_richcmpr(PyObject *a, PyObject *b, int op)
00147 {
00148     PyObject *res;
00149     int ok = -1; /* zero is true */
00150 
00151     if (ColorObject_Check(a) && ColorObject_Check(b)) {
00152         ColorObject *colA = (ColorObject *)a;
00153         ColorObject *colB = (ColorObject *)b;
00154 
00155         if (BaseMath_ReadCallback(colA) == -1 || BaseMath_ReadCallback(colB) == -1)
00156             return NULL;
00157 
00158         ok = EXPP_VectorsAreEqual(colA->col, colB->col, COLOR_SIZE, 1) ? 0 : -1;
00159     }
00160 
00161     switch (op) {
00162     case Py_NE:
00163         ok = !ok; /* pass through */
00164     case Py_EQ:
00165         res = ok ? Py_False : Py_True;
00166         break;
00167 
00168     case Py_LT:
00169     case Py_LE:
00170     case Py_GT:
00171     case Py_GE:
00172         res = Py_NotImplemented;
00173         break;
00174     default:
00175         PyErr_BadArgument();
00176         return NULL;
00177     }
00178 
00179     return Py_INCREF(res), res;
00180 }
00181 
00182 //---------------------SEQUENCE PROTOCOLS------------------------
00183 //----------------------------len(object)------------------------
00184 //sequence length
00185 static int Color_len(ColorObject *UNUSED(self))
00186 {
00187     return COLOR_SIZE;
00188 }
00189 //----------------------------object[]---------------------------
00190 //sequence accessor (get)
00191 static PyObject *Color_item(ColorObject *self, int i)
00192 {
00193     if (i < 0) i = COLOR_SIZE - i;
00194 
00195     if (i < 0 || i >= COLOR_SIZE) {
00196         PyErr_SetString(PyExc_IndexError,
00197                         "color[attribute]: "
00198                         "array index out of range");
00199         return NULL;
00200     }
00201 
00202     if (BaseMath_ReadIndexCallback(self, i) == -1)
00203         return NULL;
00204 
00205     return PyFloat_FromDouble(self->col[i]);
00206 
00207 }
00208 //----------------------------object[]-------------------------
00209 //sequence accessor (set)
00210 static int Color_ass_item(ColorObject *self, int i, PyObject *value)
00211 {
00212     float f = PyFloat_AsDouble(value);
00213 
00214     if (f == -1 && PyErr_Occurred()) { // parsed item not a number
00215         PyErr_SetString(PyExc_TypeError,
00216                         "color[attribute] = x: "
00217                         "argument not a number");
00218         return -1;
00219     }
00220 
00221     if (i < 0) i= COLOR_SIZE - i;
00222 
00223     if (i < 0 || i >= COLOR_SIZE) {
00224         PyErr_SetString(PyExc_IndexError, "color[attribute] = x: "
00225                         "array assignment index out of range");
00226         return -1;
00227     }
00228 
00229     self->col[i] = f;
00230 
00231     if (BaseMath_WriteIndexCallback(self, i) == -1)
00232         return -1;
00233 
00234     return 0;
00235 }
00236 //----------------------------object[z:y]------------------------
00237 //sequence slice (get)
00238 static PyObject *Color_slice(ColorObject *self, int begin, int end)
00239 {
00240     PyObject *tuple;
00241     int count;
00242 
00243     if (BaseMath_ReadCallback(self) == -1)
00244         return NULL;
00245 
00246     CLAMP(begin, 0, COLOR_SIZE);
00247     if (end < 0) end = (COLOR_SIZE + 1) + end;
00248     CLAMP(end, 0, COLOR_SIZE);
00249     begin = MIN2(begin, end);
00250 
00251     tuple = PyTuple_New(end - begin);
00252     for (count = begin; count < end; count++) {
00253         PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->col[count]));
00254     }
00255 
00256     return tuple;
00257 }
00258 //----------------------------object[z:y]------------------------
00259 //sequence slice (set)
00260 static int Color_ass_slice(ColorObject *self, int begin, int end, PyObject *seq)
00261 {
00262     int i, size;
00263     float col[COLOR_SIZE];
00264 
00265     if (BaseMath_ReadCallback(self) == -1)
00266         return -1;
00267 
00268     CLAMP(begin, 0, COLOR_SIZE);
00269     if (end < 0) end = (COLOR_SIZE + 1) + end;
00270     CLAMP(end, 0, COLOR_SIZE);
00271     begin = MIN2(begin, end);
00272 
00273     if ((size = mathutils_array_parse(col, 0, COLOR_SIZE, seq, "mathutils.Color[begin:end] = []")) == -1)
00274         return -1;
00275 
00276     if (size != (end - begin)) {
00277         PyErr_SetString(PyExc_ValueError,
00278                         "color[begin:end] = []: "
00279                         "size mismatch in slice assignment");
00280         return -1;
00281     }
00282 
00283     for (i = 0; i < COLOR_SIZE; i++)
00284         self->col[begin + i] = col[i];
00285 
00286     (void)BaseMath_WriteCallback(self);
00287     return 0;
00288 }
00289 
00290 static PyObject *Color_subscript(ColorObject *self, PyObject *item)
00291 {
00292     if (PyIndex_Check(item)) {
00293         Py_ssize_t i;
00294         i = PyNumber_AsSsize_t(item, PyExc_IndexError);
00295         if (i == -1 && PyErr_Occurred())
00296             return NULL;
00297         if (i < 0)
00298             i += COLOR_SIZE;
00299         return Color_item(self, i);
00300     }
00301     else if (PySlice_Check(item)) {
00302         Py_ssize_t start, stop, step, slicelength;
00303 
00304         if (PySlice_GetIndicesEx((void *)item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0)
00305             return NULL;
00306 
00307         if (slicelength <= 0) {
00308             return PyTuple_New(0);
00309         }
00310         else if (step == 1) {
00311             return Color_slice(self, start, stop);
00312         }
00313         else {
00314             PyErr_SetString(PyExc_IndexError,
00315                             "slice steps not supported with color");
00316             return NULL;
00317         }
00318     }
00319     else {
00320         PyErr_Format(PyExc_TypeError,
00321                      "color indices must be integers, not %.200s",
00322                      Py_TYPE(item)->tp_name);
00323         return NULL;
00324     }
00325 }
00326 
00327 static int Color_ass_subscript(ColorObject *self, PyObject *item, PyObject *value)
00328 {
00329     if (PyIndex_Check(item)) {
00330         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
00331         if (i == -1 && PyErr_Occurred())
00332             return -1;
00333         if (i < 0)
00334             i += COLOR_SIZE;
00335         return Color_ass_item(self, i, value);
00336     }
00337     else if (PySlice_Check(item)) {
00338         Py_ssize_t start, stop, step, slicelength;
00339 
00340         if (PySlice_GetIndicesEx((void *)item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0)
00341             return -1;
00342 
00343         if (step == 1)
00344             return Color_ass_slice(self, start, stop, value);
00345         else {
00346             PyErr_SetString(PyExc_IndexError,
00347                             "slice steps not supported with color");
00348             return -1;
00349         }
00350     }
00351     else {
00352         PyErr_Format(PyExc_TypeError,
00353                      "color indices must be integers, not %.200s",
00354                      Py_TYPE(item)->tp_name);
00355         return -1;
00356     }
00357 }
00358 
00359 //-----------------PROTCOL DECLARATIONS--------------------------
00360 static PySequenceMethods Color_SeqMethods = {
00361     (lenfunc) Color_len,                    /* sq_length */
00362     (binaryfunc) NULL,                      /* sq_concat */
00363     (ssizeargfunc) NULL,                    /* sq_repeat */
00364     (ssizeargfunc) Color_item,              /* sq_item */
00365     NULL,                                   /* sq_slice, deprecated */
00366     (ssizeobjargproc) Color_ass_item,       /* sq_ass_item */
00367     NULL,                                   /* sq_ass_slice, deprecated */
00368     (objobjproc) NULL,                      /* sq_contains */
00369     (binaryfunc) NULL,                      /* sq_inplace_concat */
00370     (ssizeargfunc) NULL,                    /* sq_inplace_repeat */
00371 };
00372 
00373 static PyMappingMethods Color_AsMapping = {
00374     (lenfunc)Color_len,
00375     (binaryfunc)Color_subscript,
00376     (objobjargproc)Color_ass_subscript
00377 };
00378 
00379 /* numeric */
00380 
00381 
00382 /* addition: obj + obj */
00383 static PyObject *Color_add(PyObject *v1, PyObject *v2)
00384 {
00385     ColorObject *color1 = NULL, *color2 = NULL;
00386     float col[COLOR_SIZE];
00387 
00388     if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
00389         PyErr_Format(PyExc_TypeError,
00390                      "Color addition: (%s + %s) "
00391                      "invalid type for this operation",
00392                      Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
00393         return NULL;
00394     }
00395     color1 = (ColorObject *)v1;
00396     color2 = (ColorObject *)v2;
00397 
00398     if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
00399         return NULL;
00400 
00401     add_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
00402 
00403     return Color_CreatePyObject(col, Py_NEW, Py_TYPE(v1));
00404 }
00405 
00406 /* addition in-place: obj += obj */
00407 static PyObject *Color_iadd(PyObject *v1, PyObject *v2)
00408 {
00409     ColorObject *color1 = NULL, *color2 = NULL;
00410 
00411     if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
00412         PyErr_Format(PyExc_TypeError,
00413                      "Color addition: (%s += %s) "
00414                      "invalid type for this operation",
00415                      Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
00416         return NULL;
00417     }
00418     color1 = (ColorObject *)v1;
00419     color2 = (ColorObject *)v2;
00420 
00421     if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
00422         return NULL;
00423 
00424     add_vn_vn(color1->col, color2->col, COLOR_SIZE);
00425 
00426     (void)BaseMath_WriteCallback(color1);
00427     Py_INCREF(v1);
00428     return v1;
00429 }
00430 
00431 /* subtraction: obj - obj */
00432 static PyObject *Color_sub(PyObject *v1, PyObject *v2)
00433 {
00434     ColorObject *color1 = NULL, *color2 = NULL;
00435     float col[COLOR_SIZE];
00436 
00437     if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
00438         PyErr_Format(PyExc_TypeError,
00439                      "Color subtraction: (%s - %s) "
00440                      "invalid type for this operation",
00441                      Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
00442         return NULL;
00443     }
00444     color1 = (ColorObject *)v1;
00445     color2 = (ColorObject *)v2;
00446 
00447     if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
00448         return NULL;
00449 
00450     sub_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
00451 
00452     return Color_CreatePyObject(col, Py_NEW, Py_TYPE(v1));
00453 }
00454 
00455 /* subtraction in-place: obj -= obj */
00456 static PyObject *Color_isub(PyObject *v1, PyObject *v2)
00457 {
00458     ColorObject *color1 = NULL, *color2 = NULL;
00459 
00460     if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
00461         PyErr_Format(PyExc_TypeError,
00462                      "Color subtraction: (%s -= %s) "
00463                      "invalid type for this operation",
00464                      Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
00465         return NULL;
00466     }
00467     color1 = (ColorObject *)v1;
00468     color2 = (ColorObject *)v2;
00469 
00470     if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
00471         return NULL;
00472 
00473     sub_vn_vn(color1->col, color2->col, COLOR_SIZE);
00474 
00475     (void)BaseMath_WriteCallback(color1);
00476     Py_INCREF(v1);
00477     return v1;
00478 }
00479 
00480 static PyObject *color_mul_float(ColorObject *color, const float scalar)
00481 {
00482     float tcol[COLOR_SIZE];
00483     mul_vn_vn_fl(tcol, color->col, COLOR_SIZE, scalar);
00484     return Color_CreatePyObject(tcol, Py_NEW, Py_TYPE(color));
00485 }
00486 
00487 
00488 static PyObject *Color_mul(PyObject *v1, PyObject *v2)
00489 {
00490     ColorObject *color1 = NULL, *color2 = NULL;
00491     float scalar;
00492 
00493     if ColorObject_Check(v1) {
00494         color1 = (ColorObject *)v1;
00495         if (BaseMath_ReadCallback(color1) == -1)
00496             return NULL;
00497     }
00498     if ColorObject_Check(v2) {
00499         color2 = (ColorObject *)v2;
00500         if (BaseMath_ReadCallback(color2) == -1)
00501             return NULL;
00502     }
00503 
00504 
00505     /* make sure v1 is always the vector */
00506     if (color1 && color2) {
00507         /* col * col, dont support yet! */
00508     }
00509     else if (color1) {
00510         if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR * FLOAT */
00511             return color_mul_float(color1, scalar);
00512         }
00513     }
00514     else if (color2) {
00515         if (((scalar = PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred()) == 0) { /* FLOAT * COLOR */
00516             return color_mul_float(color2, scalar);
00517         }
00518     }
00519     else {
00520         BLI_assert(!"internal error");
00521     }
00522 
00523     PyErr_Format(PyExc_TypeError,
00524                  "Color multiplication: not supported between "
00525                  "'%.200s' and '%.200s' types",
00526                  Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
00527     return NULL;
00528 }
00529 
00530 static PyObject *Color_div(PyObject *v1, PyObject *v2)
00531 {
00532     ColorObject *color1 = NULL;
00533     float scalar;
00534 
00535     if ColorObject_Check(v1) {
00536         color1 = (ColorObject *)v1;
00537         if (BaseMath_ReadCallback(color1) == -1)
00538             return NULL;
00539     }
00540     else {
00541         PyErr_SetString(PyExc_TypeError,
00542                         "Color division not supported in this order");
00543         return NULL;
00544     }
00545 
00546     /* make sure v1 is always the vector */
00547     if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR * FLOAT */
00548         if (scalar == 0.0f) {
00549             PyErr_SetString(PyExc_ZeroDivisionError,
00550                             "Color division: divide by zero error");
00551             return NULL;
00552         }
00553         return color_mul_float(color1, 1.0f / scalar);
00554     }
00555 
00556     PyErr_Format(PyExc_TypeError,
00557                  "Color multiplication: not supported between "
00558                  "'%.200s' and '%.200s' types",
00559                  Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
00560     return NULL;
00561 }
00562 
00563 /* mulplication in-place: obj *= obj */
00564 static PyObject *Color_imul(PyObject *v1, PyObject *v2)
00565 {
00566     ColorObject *color = (ColorObject *)v1;
00567     float scalar;
00568 
00569     if (BaseMath_ReadCallback(color) == -1)
00570         return NULL;
00571 
00572     /* only support color *= float */
00573     if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR *= FLOAT */
00574         mul_vn_fl(color->col, COLOR_SIZE, scalar);
00575     }
00576     else {
00577         PyErr_Format(PyExc_TypeError,
00578                      "Color multiplication: (%s *= %s) "
00579                      "invalid type for this operation",
00580                      Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
00581         return NULL;
00582     }
00583 
00584     (void)BaseMath_WriteCallback(color);
00585     Py_INCREF(v1);
00586     return v1;
00587 }
00588 
00589 /* mulplication in-place: obj *= obj */
00590 static PyObject *Color_idiv(PyObject *v1, PyObject *v2)
00591 {
00592     ColorObject *color = (ColorObject *)v1;
00593     float scalar;
00594 
00595     if (BaseMath_ReadCallback(color) == -1)
00596         return NULL;
00597 
00598     /* only support color /= float */
00599     if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR /= FLOAT */
00600         if (scalar == 0.0f) {
00601             PyErr_SetString(PyExc_ZeroDivisionError,
00602                             "Color division: divide by zero error");
00603             return NULL;
00604         }
00605 
00606         mul_vn_fl(color->col, COLOR_SIZE, 1.0f / scalar);
00607     }
00608     else {
00609         PyErr_Format(PyExc_TypeError,
00610                      "Color division: (%s /= %s) "
00611                      "invalid type for this operation",
00612                      Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
00613         return NULL;
00614     }
00615 
00616     (void)BaseMath_WriteCallback(color);
00617     Py_INCREF(v1);
00618     return v1;
00619 }
00620 
00621 /* -obj
00622   returns the negative of this object */
00623 static PyObject *Color_neg(ColorObject *self)
00624 {
00625     float tcol[COLOR_SIZE];
00626 
00627     if (BaseMath_ReadCallback(self) == -1)
00628         return NULL;
00629 
00630     negate_vn_vn(tcol, self->col, COLOR_SIZE);
00631     return Color_CreatePyObject(tcol, Py_NEW, Py_TYPE(self));
00632 }
00633 
00634 
00635 static PyNumberMethods Color_NumMethods = {
00636     (binaryfunc) Color_add, /*nb_add*/
00637     (binaryfunc) Color_sub, /*nb_subtract*/
00638     (binaryfunc) Color_mul, /*nb_multiply*/
00639     NULL,               /*nb_remainder*/
00640     NULL,               /*nb_divmod*/
00641     NULL,               /*nb_power*/
00642     (unaryfunc) Color_neg, /*nb_negative*/
00643     (unaryfunc) NULL,   /*tp_positive*/
00644     (unaryfunc) NULL,   /*tp_absolute*/
00645     (inquiry)   NULL,   /*tp_bool*/
00646     (unaryfunc) NULL,   /*nb_invert*/
00647     NULL,               /*nb_lshift*/
00648     (binaryfunc)NULL,   /*nb_rshift*/
00649     NULL,               /*nb_and*/
00650     NULL,               /*nb_xor*/
00651     NULL,               /*nb_or*/
00652     NULL,               /*nb_int*/
00653     NULL,               /*nb_reserved*/
00654     NULL,               /*nb_float*/
00655     Color_iadd,         /* nb_inplace_add */
00656     Color_isub,         /* nb_inplace_subtract */
00657     Color_imul,         /* nb_inplace_multiply */
00658     NULL,               /* nb_inplace_remainder */
00659     NULL,               /* nb_inplace_power */
00660     NULL,               /* nb_inplace_lshift */
00661     NULL,               /* nb_inplace_rshift */
00662     NULL,               /* nb_inplace_and */
00663     NULL,               /* nb_inplace_xor */
00664     NULL,               /* nb_inplace_or */
00665     NULL,               /* nb_floor_divide */
00666     Color_div,          /* nb_true_divide */
00667     NULL,               /* nb_inplace_floor_divide */
00668     Color_idiv,         /* nb_inplace_true_divide */
00669     NULL,               /* nb_index */
00670 };
00671 
00672 /* color channel, vector.r/g/b */
00673 PyDoc_STRVAR(Color_channel_r_doc, "Red color channel.\n\n:type: float");
00674 PyDoc_STRVAR(Color_channel_g_doc, "Green color channel.\n\n:type: float");
00675 PyDoc_STRVAR(Color_channel_b_doc, "Blue color channel.\n\n:type: float");
00676 
00677 static PyObject *Color_channel_get(ColorObject *self, void *type)
00678 {
00679     return Color_item(self, GET_INT_FROM_POINTER(type));
00680 }
00681 
00682 static int Color_channel_set(ColorObject *self, PyObject *value, void * type)
00683 {
00684     return Color_ass_item(self, GET_INT_FROM_POINTER(type), value);
00685 }
00686 
00687 /* color channel (HSV), color.h/s/v */
00688 PyDoc_STRVAR(Color_channel_hsv_h_doc, "HSV Hue component in [0, 1].\n\n:type: float");
00689 PyDoc_STRVAR(Color_channel_hsv_s_doc, "HSV Saturation component in [0, 1].\n\n:type: float");
00690 PyDoc_STRVAR(Color_channel_hsv_v_doc, "HSV Value component in [0, 1].\n\n:type: float");
00691 
00692 static PyObject *Color_channel_hsv_get(ColorObject *self, void *type)
00693 {
00694     float hsv[3];
00695     int i = GET_INT_FROM_POINTER(type);
00696 
00697     if (BaseMath_ReadCallback(self) == -1)
00698         return NULL;
00699 
00700     rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
00701 
00702     return PyFloat_FromDouble(hsv[i]);
00703 }
00704 
00705 static int Color_channel_hsv_set(ColorObject *self, PyObject *value, void * type)
00706 {
00707     float hsv[3];
00708     int i = GET_INT_FROM_POINTER(type);
00709     float f = PyFloat_AsDouble(value);
00710 
00711     if (f == -1 && PyErr_Occurred()) {
00712         PyErr_SetString(PyExc_TypeError,
00713                         "color.h/s/v = value: "
00714                         "argument not a number");
00715         return -1;
00716     }
00717 
00718     if (BaseMath_ReadCallback(self) == -1)
00719         return -1;
00720 
00721     rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
00722     CLAMP(f, 0.0f, 1.0f);
00723     hsv[i] = f;
00724     hsv_to_rgb(hsv[0], hsv[1], hsv[2], &(self->col[0]), &(self->col[1]), &(self->col[2]));
00725 
00726     if (BaseMath_WriteCallback(self) == -1)
00727         return -1;
00728 
00729     return 0;
00730 }
00731 
00732 /* color channel (HSV), color.h/s/v */
00733 PyDoc_STRVAR(Color_hsv_doc, "HSV Values in [0, 1].\n\n:type: float triplet");
00734 static PyObject *Color_hsv_get(ColorObject *self, void *UNUSED(closure))
00735 {
00736     float hsv[3];
00737     PyObject *ret;
00738 
00739     if (BaseMath_ReadCallback(self) == -1)
00740         return NULL;
00741 
00742     rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
00743 
00744     ret = PyTuple_New(3);
00745     PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(hsv[0]));
00746     PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(hsv[1]));
00747     PyTuple_SET_ITEM(ret, 2, PyFloat_FromDouble(hsv[2]));
00748     return ret;
00749 }
00750 
00751 static int Color_hsv_set(ColorObject *self, PyObject *value, void *UNUSED(closure))
00752 {
00753     float hsv[3];
00754 
00755     if (mathutils_array_parse(hsv, 3, 3, value, "mathutils.Color.hsv = value") == -1)
00756         return -1;
00757 
00758     CLAMP(hsv[0], 0.0f, 1.0f);
00759     CLAMP(hsv[1], 0.0f, 1.0f);
00760     CLAMP(hsv[2], 0.0f, 1.0f);
00761 
00762     hsv_to_rgb(hsv[0], hsv[1], hsv[2], &(self->col[0]), &(self->col[1]), &(self->col[2]));
00763 
00764     if (BaseMath_WriteCallback(self) == -1)
00765         return -1;
00766 
00767     return 0;
00768 }
00769 
00770 /*****************************************************************************/
00771 /* Python attributes get/set structure:                                      */
00772 /*****************************************************************************/
00773 static PyGetSetDef Color_getseters[] = {
00774     {(char *)"r", (getter)Color_channel_get, (setter)Color_channel_set, Color_channel_r_doc, (void *)0},
00775     {(char *)"g", (getter)Color_channel_get, (setter)Color_channel_set, Color_channel_g_doc, (void *)1},
00776     {(char *)"b", (getter)Color_channel_get, (setter)Color_channel_set, Color_channel_b_doc, (void *)2},
00777 
00778     {(char *)"h", (getter)Color_channel_hsv_get, (setter)Color_channel_hsv_set, (char *)Color_channel_hsv_h_doc, (void *)0},
00779     {(char *)"s", (getter)Color_channel_hsv_get, (setter)Color_channel_hsv_set, (char *)Color_channel_hsv_s_doc, (void *)1},
00780     {(char *)"v", (getter)Color_channel_hsv_get, (setter)Color_channel_hsv_set, (char *)Color_channel_hsv_v_doc, (void *)2},
00781 
00782     {(char *)"hsv", (getter)Color_hsv_get, (setter)Color_hsv_set, (char *)Color_hsv_doc, (void *)0},
00783 
00784     {(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL},
00785     {(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
00786     {NULL, NULL, NULL, NULL, NULL}  /* Sentinel */
00787 };
00788 
00789 
00790 //-----------------------METHOD DEFINITIONS ----------------------
00791 static struct PyMethodDef Color_methods[] = {
00792     {"__copy__", (PyCFunction) Color_copy, METH_NOARGS, Color_copy_doc},
00793     {"copy", (PyCFunction) Color_copy, METH_NOARGS, Color_copy_doc},
00794     {NULL, NULL, 0, NULL}
00795 };
00796 
00797 //------------------PY_OBECT DEFINITION--------------------------
00798 PyDoc_STRVAR(color_doc,
00799 "This object gives access to Colors in Blender."
00800 );
00801 PyTypeObject color_Type = {
00802     PyVarObject_HEAD_INIT(NULL, 0)
00803     "mathutils.Color",              //tp_name
00804     sizeof(ColorObject),            //tp_basicsize
00805     0,                              //tp_itemsize
00806     (destructor)BaseMathObject_dealloc,     //tp_dealloc
00807     NULL,                           //tp_print
00808     NULL,                           //tp_getattr
00809     NULL,                           //tp_setattr
00810     NULL,                           //tp_compare
00811     (reprfunc) Color_repr,          //tp_repr
00812     &Color_NumMethods,              //tp_as_number
00813     &Color_SeqMethods,              //tp_as_sequence
00814     &Color_AsMapping,               //tp_as_mapping
00815     NULL,                           //tp_hash
00816     NULL,                           //tp_call
00817     (reprfunc) Color_str,           //tp_str
00818     NULL,                           //tp_getattro
00819     NULL,                           //tp_setattro
00820     NULL,                           //tp_as_buffer
00821     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, //tp_flags
00822     color_doc, //tp_doc
00823     (traverseproc)BaseMathObject_traverse,  //tp_traverse
00824     (inquiry)BaseMathObject_clear,  //tp_clear
00825     (richcmpfunc)Color_richcmpr,    //tp_richcompare
00826     0,                              //tp_weaklistoffset
00827     NULL,                           //tp_iter
00828     NULL,                           //tp_iternext
00829     Color_methods,                  //tp_methods
00830     NULL,                           //tp_members
00831     Color_getseters,                //tp_getset
00832     NULL,                           //tp_base
00833     NULL,                           //tp_dict
00834     NULL,                           //tp_descr_get
00835     NULL,                           //tp_descr_set
00836     0,                              //tp_dictoffset
00837     NULL,                           //tp_init
00838     NULL,                           //tp_alloc
00839     Color_new,                      //tp_new
00840     NULL,                           //tp_free
00841     NULL,                           //tp_is_gc
00842     NULL,                           //tp_bases
00843     NULL,                           //tp_mro
00844     NULL,                           //tp_cache
00845     NULL,                           //tp_subclasses
00846     NULL,                           //tp_weaklist
00847     NULL                            //tp_del
00848 };
00849 //------------------------Color_CreatePyObject (internal)-------------
00850 //creates a new color object
00851 /*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
00852  (i.e. it was allocated elsewhere by MEM_mallocN())
00853   pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
00854  (i.e. it must be created here with PyMEM_malloc())*/
00855 PyObject *Color_CreatePyObject(float *col, int type, PyTypeObject *base_type)
00856 {
00857     ColorObject *self;
00858 
00859     self = base_type ?  (ColorObject *)base_type->tp_alloc(base_type, 0) :
00860                         (ColorObject *)PyObject_GC_New(ColorObject, &color_Type);
00861 
00862     if (self) {
00863         /* init callbacks as NULL */
00864         self->cb_user = NULL;
00865         self->cb_type = self->cb_subtype = 0;
00866 
00867         if (type == Py_WRAP) {
00868             self->col = col;
00869             self->wrapped = Py_WRAP;
00870         }
00871         else if (type == Py_NEW) {
00872             self->col = PyMem_Malloc(COLOR_SIZE * sizeof(float));
00873             if (col)
00874                 copy_v3_v3(self->col, col);
00875             else
00876                 zero_v3(self->col);
00877 
00878             self->wrapped = Py_NEW;
00879         }
00880         else {
00881             Py_FatalError("Color(): invalid type!");
00882         }
00883     }
00884 
00885     return (PyObject *)self;
00886 }
00887 
00888 PyObject *Color_CreatePyObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
00889 {
00890     ColorObject *self = (ColorObject *)Color_CreatePyObject(NULL, Py_NEW, NULL);
00891     if (self) {
00892         Py_INCREF(cb_user);
00893         self->cb_user =         cb_user;
00894         self->cb_type =         (unsigned char)cb_type;
00895         self->cb_subtype =      (unsigned char)cb_subtype;
00896         PyObject_GC_Track(self);
00897     }
00898 
00899     return (PyObject *)self;
00900 }