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