Blender  V2.93
mathutils_Color.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include <Python.h>
22 
23 #include "mathutils.h"
24 
25 #include "BLI_math.h"
26 #include "BLI_utildefines.h"
27 
28 #include "../generic/py_capi_utils.h"
29 #include "../generic/python_utildefines.h"
30 
31 #ifndef MATH_STANDALONE
32 # include "BLI_dynstr.h"
33 #endif
34 
35 #define COLOR_SIZE 3
36 
37 /* ----------------------------------mathutils.Color() ------------------- */
38 /* makes a new color for you to play with */
39 static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
40 {
41  float col[3] = {0.0f, 0.0f, 0.0f};
42 
43  if (kwds && PyDict_Size(kwds)) {
44  PyErr_SetString(PyExc_TypeError,
45  "mathutils.Color(): "
46  "takes no keyword args");
47  return NULL;
48  }
49 
50  switch (PyTuple_GET_SIZE(args)) {
51  case 0:
52  break;
53  case 1:
55  col, COLOR_SIZE, COLOR_SIZE, PyTuple_GET_ITEM(args, 0), "mathutils.Color()")) ==
56  -1) {
57  return NULL;
58  }
59  break;
60  default:
61  PyErr_SetString(PyExc_TypeError,
62  "mathutils.Color(): "
63  "more than a single arg given");
64  return NULL;
65  }
66  return Color_CreatePyObject(col, type);
67 }
68 
69 /* -----------------------------METHODS---------------------------- */
70 
71 /* note: BaseMath_ReadCallback must be called beforehand */
72 static PyObject *Color_ToTupleExt(ColorObject *self, int ndigits)
73 {
74  PyObject *ret;
75  int i;
76 
77  ret = PyTuple_New(COLOR_SIZE);
78 
79  if (ndigits >= 0) {
80  for (i = 0; i < COLOR_SIZE; i++) {
81  PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->col[i], ndigits)));
82  }
83  }
84  else {
85  for (i = 0; i < COLOR_SIZE; i++) {
86  PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->col[i]));
87  }
88  }
89 
90  return ret;
91 }
92 
93 PyDoc_STRVAR(Color_copy_doc,
94  ".. function:: copy()\n"
95  "\n"
96  " Returns a copy of this color.\n"
97  "\n"
98  " :return: A copy of the color.\n"
99  " :rtype: :class:`Color`\n"
100  "\n"
101  " .. note:: use this to get a copy of a wrapped color with\n"
102  " no reference to the original data.\n");
103 static PyObject *Color_copy(ColorObject *self)
104 {
105  if (BaseMath_ReadCallback(self) == -1) {
106  return NULL;
107  }
108 
109  return Color_CreatePyObject(self->col, Py_TYPE(self));
110 }
111 static PyObject *Color_deepcopy(ColorObject *self, PyObject *args)
112 {
113  if (!PyC_CheckArgs_DeepCopy(args)) {
114  return NULL;
115  }
116  return Color_copy(self);
117 }
118 
119 /* ----------------------------print object (internal)-------------- */
120 /* print the object to screen */
121 
122 static PyObject *Color_repr(ColorObject *self)
123 {
124  PyObject *ret, *tuple;
125 
126  if (BaseMath_ReadCallback(self) == -1) {
127  return NULL;
128  }
129 
130  tuple = Color_ToTupleExt(self, -1);
131 
132  ret = PyUnicode_FromFormat("Color(%R)", tuple);
133 
134  Py_DECREF(tuple);
135  return ret;
136 }
137 
138 #ifndef MATH_STANDALONE
139 static PyObject *Color_str(ColorObject *self)
140 {
141  DynStr *ds;
142 
143  if (BaseMath_ReadCallback(self) == -1) {
144  return NULL;
145  }
146 
147  ds = BLI_dynstr_new();
148 
150  ds, "<Color (r=%.4f, g=%.4f, b=%.4f)>", self->col[0], self->col[1], self->col[2]);
151 
152  return mathutils_dynstr_to_py(ds); /* frees ds */
153 }
154 #endif
155 
156 /* ------------------------tp_richcmpr */
157 /* returns -1 exception, 0 false, 1 true */
158 static PyObject *Color_richcmpr(PyObject *a, PyObject *b, int op)
159 {
160  PyObject *res;
161  int ok = -1; /* zero is true */
162 
164  ColorObject *colA = (ColorObject *)a;
165  ColorObject *colB = (ColorObject *)b;
166 
167  if (BaseMath_ReadCallback(colA) == -1 || BaseMath_ReadCallback(colB) == -1) {
168  return NULL;
169  }
170 
171  ok = EXPP_VectorsAreEqual(colA->col, colB->col, COLOR_SIZE, 1) ? 0 : -1;
172  }
173 
174  switch (op) {
175  case Py_NE:
176  ok = !ok;
178  case Py_EQ:
179  res = ok ? Py_False : Py_True;
180  break;
181 
182  case Py_LT:
183  case Py_LE:
184  case Py_GT:
185  case Py_GE:
186  res = Py_NotImplemented;
187  break;
188  default:
189  PyErr_BadArgument();
190  return NULL;
191  }
192 
193  return Py_INCREF_RET(res);
194 }
195 
196 static Py_hash_t Color_hash(ColorObject *self)
197 {
198  if (BaseMath_ReadCallback(self) == -1) {
199  return -1;
200  }
201 
202  if (BaseMathObject_Prepare_ForHash(self) == -1) {
203  return -1;
204  }
205 
206  return mathutils_array_hash(self->col, COLOR_SIZE);
207 }
208 
209 /* ---------------------SEQUENCE PROTOCOLS------------------------ */
210 /* ----------------------------len(object)------------------------ */
211 /* sequence length */
212 static int Color_len(ColorObject *UNUSED(self))
213 {
214  return COLOR_SIZE;
215 }
216 /* ----------------------------object[]--------------------------- */
217 /* sequence accessor (get) */
218 static PyObject *Color_item(ColorObject *self, int i)
219 {
220  if (i < 0) {
221  i = COLOR_SIZE - i;
222  }
223 
224  if (i < 0 || i >= COLOR_SIZE) {
225  PyErr_SetString(PyExc_IndexError,
226  "color[item]: "
227  "array index out of range");
228  return NULL;
229  }
230 
231  if (BaseMath_ReadIndexCallback(self, i) == -1) {
232  return NULL;
233  }
234 
235  return PyFloat_FromDouble(self->col[i]);
236 }
237 /* ----------------------------object[]------------------------- */
238 /* sequence accessor (set) */
239 static int Color_ass_item(ColorObject *self, int i, PyObject *value)
240 {
241  float f;
242 
243  if (BaseMath_Prepare_ForWrite(self) == -1) {
244  return -1;
245  }
246 
247  f = PyFloat_AsDouble(value);
248  if (f == -1 && PyErr_Occurred()) { /* parsed item not a number */
249  PyErr_SetString(PyExc_TypeError,
250  "color[item] = x: "
251  "assigned value not a number");
252  return -1;
253  }
254 
255  if (i < 0) {
256  i = COLOR_SIZE - i;
257  }
258 
259  if (i < 0 || i >= COLOR_SIZE) {
260  PyErr_SetString(PyExc_IndexError,
261  "color[item] = x: "
262  "array assignment index out of range");
263  return -1;
264  }
265 
266  self->col[i] = f;
267 
268  if (BaseMath_WriteIndexCallback(self, i) == -1) {
269  return -1;
270  }
271 
272  return 0;
273 }
274 /* ----------------------------object[z:y]------------------------ */
275 /* sequence slice (get) */
276 static PyObject *Color_slice(ColorObject *self, int begin, int end)
277 {
278  PyObject *tuple;
279  int count;
280 
281  if (BaseMath_ReadCallback(self) == -1) {
282  return NULL;
283  }
284 
285  CLAMP(begin, 0, COLOR_SIZE);
286  if (end < 0) {
287  end = (COLOR_SIZE + 1) + end;
288  }
289  CLAMP(end, 0, COLOR_SIZE);
290  begin = MIN2(begin, end);
291 
292  tuple = PyTuple_New(end - begin);
293  for (count = begin; count < end; count++) {
294  PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->col[count]));
295  }
296 
297  return tuple;
298 }
299 /* ----------------------------object[z:y]------------------------ */
300 /* sequence slice (set) */
301 static int Color_ass_slice(ColorObject *self, int begin, int end, PyObject *seq)
302 {
303  int i, size;
304  float col[COLOR_SIZE];
305 
306  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
307  return -1;
308  }
309 
310  CLAMP(begin, 0, COLOR_SIZE);
311  if (end < 0) {
312  end = (COLOR_SIZE + 1) + end;
313  }
314  CLAMP(end, 0, COLOR_SIZE);
315  begin = MIN2(begin, end);
316 
317  if ((size = mathutils_array_parse(col, 0, COLOR_SIZE, seq, "mathutils.Color[begin:end] = []")) ==
318  -1) {
319  return -1;
320  }
321 
322  if (size != (end - begin)) {
323  PyErr_SetString(PyExc_ValueError,
324  "color[begin:end] = []: "
325  "size mismatch in slice assignment");
326  return -1;
327  }
328 
329  for (i = 0; i < COLOR_SIZE; i++) {
330  self->col[begin + i] = col[i];
331  }
332 
333  (void)BaseMath_WriteCallback(self);
334  return 0;
335 }
336 
337 static PyObject *Color_subscript(ColorObject *self, PyObject *item)
338 {
339  if (PyIndex_Check(item)) {
340  Py_ssize_t i;
341  i = PyNumber_AsSsize_t(item, PyExc_IndexError);
342  if (i == -1 && PyErr_Occurred()) {
343  return NULL;
344  }
345  if (i < 0) {
346  i += COLOR_SIZE;
347  }
348  return Color_item(self, i);
349  }
350  if (PySlice_Check(item)) {
351  Py_ssize_t start, stop, step, slicelength;
352 
353  if (PySlice_GetIndicesEx(item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0) {
354  return NULL;
355  }
356 
357  if (slicelength <= 0) {
358  return PyTuple_New(0);
359  }
360  if (step == 1) {
361  return Color_slice(self, start, stop);
362  }
363 
364  PyErr_SetString(PyExc_IndexError, "slice steps not supported with color");
365  return NULL;
366  }
367 
368  PyErr_Format(
369  PyExc_TypeError, "color indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
370  return NULL;
371 }
372 
373 static int Color_ass_subscript(ColorObject *self, PyObject *item, PyObject *value)
374 {
375  if (PyIndex_Check(item)) {
376  Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
377  if (i == -1 && PyErr_Occurred()) {
378  return -1;
379  }
380  if (i < 0) {
381  i += COLOR_SIZE;
382  }
383  return Color_ass_item(self, i, value);
384  }
385  if (PySlice_Check(item)) {
386  Py_ssize_t start, stop, step, slicelength;
387 
388  if (PySlice_GetIndicesEx(item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0) {
389  return -1;
390  }
391 
392  if (step == 1) {
393  return Color_ass_slice(self, start, stop, value);
394  }
395 
396  PyErr_SetString(PyExc_IndexError, "slice steps not supported with color");
397  return -1;
398  }
399 
400  PyErr_Format(
401  PyExc_TypeError, "color indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
402  return -1;
403 }
404 
405 /* -----------------PROTCOL DECLARATIONS-------------------------- */
406 static PySequenceMethods Color_SeqMethods = {
407  (lenfunc)Color_len, /* sq_length */
408  (binaryfunc)NULL, /* sq_concat */
409  (ssizeargfunc)NULL, /* sq_repeat */
410  (ssizeargfunc)Color_item, /* sq_item */
411  NULL, /* sq_slice, deprecated */
412  (ssizeobjargproc)Color_ass_item, /* sq_ass_item */
413  NULL, /* sq_ass_slice, deprecated */
414  (objobjproc)NULL, /* sq_contains */
415  (binaryfunc)NULL, /* sq_inplace_concat */
416  (ssizeargfunc)NULL, /* sq_inplace_repeat */
417 };
418 
419 static PyMappingMethods Color_AsMapping = {
420  (lenfunc)Color_len,
421  (binaryfunc)Color_subscript,
422  (objobjargproc)Color_ass_subscript,
423 };
424 
425 /* numeric */
426 
427 /* addition: obj + obj */
428 static PyObject *Color_add(PyObject *v1, PyObject *v2)
429 {
430  ColorObject *color1 = NULL, *color2 = NULL;
431  float col[COLOR_SIZE];
432 
434  PyErr_Format(PyExc_TypeError,
435  "Color addition: (%s + %s) "
436  "invalid type for this operation",
437  Py_TYPE(v1)->tp_name,
438  Py_TYPE(v2)->tp_name);
439  return NULL;
440  }
441  color1 = (ColorObject *)v1;
442  color2 = (ColorObject *)v2;
443 
444  if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) {
445  return NULL;
446  }
447 
448  add_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
449 
450  return Color_CreatePyObject(col, Py_TYPE(v1));
451 }
452 
453 /* addition in-place: obj += obj */
454 static PyObject *Color_iadd(PyObject *v1, PyObject *v2)
455 {
456  ColorObject *color1 = NULL, *color2 = NULL;
457 
459  PyErr_Format(PyExc_TypeError,
460  "Color addition: (%s += %s) "
461  "invalid type for this operation",
462  Py_TYPE(v1)->tp_name,
463  Py_TYPE(v2)->tp_name);
464  return NULL;
465  }
466  color1 = (ColorObject *)v1;
467  color2 = (ColorObject *)v2;
468 
469  if (BaseMath_ReadCallback_ForWrite(color1) == -1 || BaseMath_ReadCallback(color2) == -1) {
470  return NULL;
471  }
472 
473  add_vn_vn(color1->col, color2->col, COLOR_SIZE);
474 
475  (void)BaseMath_WriteCallback(color1);
476  Py_INCREF(v1);
477  return v1;
478 }
479 
480 /* subtraction: obj - obj */
481 static PyObject *Color_sub(PyObject *v1, PyObject *v2)
482 {
483  ColorObject *color1 = NULL, *color2 = NULL;
484  float col[COLOR_SIZE];
485 
487  PyErr_Format(PyExc_TypeError,
488  "Color subtraction: (%s - %s) "
489  "invalid type for this operation",
490  Py_TYPE(v1)->tp_name,
491  Py_TYPE(v2)->tp_name);
492  return NULL;
493  }
494  color1 = (ColorObject *)v1;
495  color2 = (ColorObject *)v2;
496 
497  if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) {
498  return NULL;
499  }
500 
501  sub_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
502 
503  return Color_CreatePyObject(col, Py_TYPE(v1));
504 }
505 
506 /* subtraction in-place: obj -= obj */
507 static PyObject *Color_isub(PyObject *v1, PyObject *v2)
508 {
509  ColorObject *color1 = NULL, *color2 = NULL;
510 
512  PyErr_Format(PyExc_TypeError,
513  "Color subtraction: (%s -= %s) "
514  "invalid type for this operation",
515  Py_TYPE(v1)->tp_name,
516  Py_TYPE(v2)->tp_name);
517  return NULL;
518  }
519  color1 = (ColorObject *)v1;
520  color2 = (ColorObject *)v2;
521 
522  if (BaseMath_ReadCallback_ForWrite(color1) == -1 || BaseMath_ReadCallback(color2) == -1) {
523  return NULL;
524  }
525 
526  sub_vn_vn(color1->col, color2->col, COLOR_SIZE);
527 
528  (void)BaseMath_WriteCallback(color1);
529  Py_INCREF(v1);
530  return v1;
531 }
532 
533 static PyObject *color_mul_float(ColorObject *color, const float scalar)
534 {
535  float tcol[COLOR_SIZE];
536  mul_vn_vn_fl(tcol, color->col, COLOR_SIZE, scalar);
537  return Color_CreatePyObject(tcol, Py_TYPE(color));
538 }
539 
540 static PyObject *Color_mul(PyObject *v1, PyObject *v2)
541 {
542  ColorObject *color1 = NULL, *color2 = NULL;
543  float scalar;
544 
545  if (ColorObject_Check(v1)) {
546  color1 = (ColorObject *)v1;
547  if (BaseMath_ReadCallback(color1) == -1) {
548  return NULL;
549  }
550  }
551  if (ColorObject_Check(v2)) {
552  color2 = (ColorObject *)v2;
553  if (BaseMath_ReadCallback(color2) == -1) {
554  return NULL;
555  }
556  }
557 
558  /* make sure v1 is always the vector */
559  if (color1 && color2) {
560  /* col * col, don't support yet! */
561  }
562  else if (color1) {
563  if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR * FLOAT */
564  return color_mul_float(color1, scalar);
565  }
566  }
567  else if (color2) {
568  if (((scalar = PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred()) == 0) { /* FLOAT * COLOR */
569  return color_mul_float(color2, scalar);
570  }
571  }
572  else {
573  BLI_assert(!"internal error");
574  }
575 
576  PyErr_Format(PyExc_TypeError,
577  "Color multiplication: not supported between "
578  "'%.200s' and '%.200s' types",
579  Py_TYPE(v1)->tp_name,
580  Py_TYPE(v2)->tp_name);
581  return NULL;
582 }
583 
584 static PyObject *Color_div(PyObject *v1, PyObject *v2)
585 {
586  ColorObject *color1 = NULL;
587  float scalar;
588 
589  if (ColorObject_Check(v1)) {
590  color1 = (ColorObject *)v1;
591  if (BaseMath_ReadCallback(color1) == -1) {
592  return NULL;
593  }
594  }
595  else {
596  PyErr_SetString(PyExc_TypeError, "Color division not supported in this order");
597  return NULL;
598  }
599 
600  /* make sure v1 is always the vector */
601  if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR * FLOAT */
602  if (scalar == 0.0f) {
603  PyErr_SetString(PyExc_ZeroDivisionError, "Color division: divide by zero error");
604  return NULL;
605  }
606  return color_mul_float(color1, 1.0f / scalar);
607  }
608 
609  PyErr_Format(PyExc_TypeError,
610  "Color multiplication: not supported between "
611  "'%.200s' and '%.200s' types",
612  Py_TYPE(v1)->tp_name,
613  Py_TYPE(v2)->tp_name);
614  return NULL;
615 }
616 
617 /* multiplication in-place: obj *= obj */
618 static PyObject *Color_imul(PyObject *v1, PyObject *v2)
619 {
620  ColorObject *color = (ColorObject *)v1;
621  float scalar;
622 
623  if (BaseMath_ReadCallback_ForWrite(color) == -1) {
624  return NULL;
625  }
626 
627  /* only support color *= float */
628  if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR *= FLOAT */
629  mul_vn_fl(color->col, COLOR_SIZE, scalar);
630  }
631  else {
632  PyErr_Format(PyExc_TypeError,
633  "Color multiplication: (%s *= %s) "
634  "invalid type for this operation",
635  Py_TYPE(v1)->tp_name,
636  Py_TYPE(v2)->tp_name);
637  return NULL;
638  }
639 
640  (void)BaseMath_WriteCallback(color);
641  Py_INCREF(v1);
642  return v1;
643 }
644 
645 /* multiplication in-place: obj *= obj */
646 static PyObject *Color_idiv(PyObject *v1, PyObject *v2)
647 {
648  ColorObject *color = (ColorObject *)v1;
649  float scalar;
650 
651  if (BaseMath_ReadCallback_ForWrite(color) == -1) {
652  return NULL;
653  }
654 
655  /* only support color /= float */
656  if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR /= FLOAT */
657  if (scalar == 0.0f) {
658  PyErr_SetString(PyExc_ZeroDivisionError, "Color division: divide by zero error");
659  return NULL;
660  }
661 
662  mul_vn_fl(color->col, COLOR_SIZE, 1.0f / scalar);
663  }
664  else {
665  PyErr_Format(PyExc_TypeError,
666  "Color division: (%s /= %s) "
667  "invalid type for this operation",
668  Py_TYPE(v1)->tp_name,
669  Py_TYPE(v2)->tp_name);
670  return NULL;
671  }
672 
673  (void)BaseMath_WriteCallback(color);
674  Py_INCREF(v1);
675  return v1;
676 }
677 
678 /* -obj
679  * returns the negative of this object */
680 static PyObject *Color_neg(ColorObject *self)
681 {
682  float tcol[COLOR_SIZE];
683 
684  if (BaseMath_ReadCallback(self) == -1) {
685  return NULL;
686  }
687 
688  negate_vn_vn(tcol, self->col, COLOR_SIZE);
689  return Color_CreatePyObject(tcol, Py_TYPE(self));
690 }
691 
692 static PyNumberMethods Color_NumMethods = {
693  (binaryfunc)Color_add, /*nb_add*/
694  (binaryfunc)Color_sub, /*nb_subtract*/
695  (binaryfunc)Color_mul, /*nb_multiply*/
696  NULL, /*nb_remainder*/
697  NULL, /*nb_divmod*/
698  NULL, /*nb_power*/
699  (unaryfunc)Color_neg, /*nb_negative*/
700  (unaryfunc)Color_copy, /*tp_positive*/
701  (unaryfunc)NULL, /*tp_absolute*/
702  (inquiry)NULL, /*tp_bool*/
703  (unaryfunc)NULL, /*nb_invert*/
704  NULL, /*nb_lshift*/
705  (binaryfunc)NULL, /*nb_rshift*/
706  NULL, /*nb_and*/
707  NULL, /*nb_xor*/
708  NULL, /*nb_or*/
709  NULL, /*nb_int*/
710  NULL, /*nb_reserved*/
711  NULL, /*nb_float*/
712  Color_iadd, /* nb_inplace_add */
713  Color_isub, /* nb_inplace_subtract */
714  Color_imul, /* nb_inplace_multiply */
715  NULL, /* nb_inplace_remainder */
716  NULL, /* nb_inplace_power */
717  NULL, /* nb_inplace_lshift */
718  NULL, /* nb_inplace_rshift */
719  NULL, /* nb_inplace_and */
720  NULL, /* nb_inplace_xor */
721  NULL, /* nb_inplace_or */
722  NULL, /* nb_floor_divide */
723  Color_div, /* nb_true_divide */
724  NULL, /* nb_inplace_floor_divide */
725  Color_idiv, /* nb_inplace_true_divide */
726  NULL, /* nb_index */
727 };
728 
729 /* color channel, vector.r/g/b */
730 PyDoc_STRVAR(Color_channel_r_doc, "Red color channel.\n\n:type: float");
731 PyDoc_STRVAR(Color_channel_g_doc, "Green color channel.\n\n:type: float");
732 PyDoc_STRVAR(Color_channel_b_doc, "Blue color channel.\n\n:type: float");
733 
734 static PyObject *Color_channel_get(ColorObject *self, void *type)
735 {
736  return Color_item(self, POINTER_AS_INT(type));
737 }
738 
739 static int Color_channel_set(ColorObject *self, PyObject *value, void *type)
740 {
741  return Color_ass_item(self, POINTER_AS_INT(type), value);
742 }
743 
744 /* color channel (HSV), color.h/s/v */
745 PyDoc_STRVAR(Color_channel_hsv_h_doc, "HSV Hue component in [0, 1].\n\n:type: float");
746 PyDoc_STRVAR(Color_channel_hsv_s_doc, "HSV Saturation component in [0, 1].\n\n:type: float");
747 PyDoc_STRVAR(Color_channel_hsv_v_doc, "HSV Value component in [0, 1].\n\n:type: float");
748 
749 static PyObject *Color_channel_hsv_get(ColorObject *self, void *type)
750 {
751  float hsv[3];
752  const int i = POINTER_AS_INT(type);
753 
754  if (BaseMath_ReadCallback(self) == -1) {
755  return NULL;
756  }
757 
758  rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
759 
760  return PyFloat_FromDouble(hsv[i]);
761 }
762 
763 static int Color_channel_hsv_set(ColorObject *self, PyObject *value, void *type)
764 {
765  float hsv[3];
766  const int i = POINTER_AS_INT(type);
767  float f = PyFloat_AsDouble(value);
768 
769  if (f == -1 && PyErr_Occurred()) {
770  PyErr_SetString(PyExc_TypeError,
771  "color.h/s/v = value: "
772  "assigned value not a number");
773  return -1;
774  }
775 
776  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
777  return -1;
778  }
779 
780  rgb_to_hsv_v(self->col, hsv);
781  CLAMP(f, 0.0f, 1.0f);
782  hsv[i] = f;
783  hsv_to_rgb_v(hsv, self->col);
784 
785  if (BaseMath_WriteCallback(self) == -1) {
786  return -1;
787  }
788 
789  return 0;
790 }
791 
792 /* color channel (HSV), color.h/s/v */
793 PyDoc_STRVAR(Color_hsv_doc, "HSV Values in [0, 1].\n\n:type: float triplet");
794 static PyObject *Color_hsv_get(ColorObject *self, void *UNUSED(closure))
795 {
796  float hsv[3];
797  PyObject *ret;
798 
799  if (BaseMath_ReadCallback(self) == -1) {
800  return NULL;
801  }
802 
803  rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
804 
805  ret = PyTuple_New(3);
807  ret, PyFloat_FromDouble(hsv[0]), PyFloat_FromDouble(hsv[1]), PyFloat_FromDouble(hsv[2]));
808  return ret;
809 }
810 
811 static int Color_hsv_set(ColorObject *self, PyObject *value, void *UNUSED(closure))
812 {
813  float hsv[3];
814 
815  if (mathutils_array_parse(hsv, 3, 3, value, "mathutils.Color.hsv = value") == -1) {
816  return -1;
817  }
818 
819  if (BaseMath_Prepare_ForWrite(self) == -1) {
820  return -1;
821  }
822 
823  clamp_v3(hsv, 0.0f, 1.0f);
824  hsv_to_rgb_v(hsv, self->col);
825 
826  if (BaseMath_WriteCallback(self) == -1) {
827  return -1;
828  }
829 
830  return 0;
831 }
832 
833 /*****************************************************************************/
834 /* Python attributes get/set structure: */
835 /*****************************************************************************/
836 static PyGetSetDef Color_getseters[] = {
837  {"r", (getter)Color_channel_get, (setter)Color_channel_set, Color_channel_r_doc, (void *)0},
838  {"g", (getter)Color_channel_get, (setter)Color_channel_set, Color_channel_g_doc, (void *)1},
839  {"b", (getter)Color_channel_get, (setter)Color_channel_set, Color_channel_b_doc, (void *)2},
840 
841  {"h",
842  (getter)Color_channel_hsv_get,
843  (setter)Color_channel_hsv_set,
844  Color_channel_hsv_h_doc,
845  (void *)0},
846  {"s",
847  (getter)Color_channel_hsv_get,
848  (setter)Color_channel_hsv_set,
849  Color_channel_hsv_s_doc,
850  (void *)1},
851  {"v",
852  (getter)Color_channel_hsv_get,
853  (setter)Color_channel_hsv_set,
854  Color_channel_hsv_v_doc,
855  (void *)2},
856 
857  {"hsv", (getter)Color_hsv_get, (setter)Color_hsv_set, Color_hsv_doc, (void *)0},
858 
859  {"is_wrapped",
861  (setter)NULL,
863  NULL},
864  {"is_frozen",
866  (setter)NULL,
868  NULL},
869  {"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
870  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
871 };
872 
873 /* -----------------------METHOD DEFINITIONS ---------------------- */
874 static struct PyMethodDef Color_methods[] = {
875  {"copy", (PyCFunction)Color_copy, METH_NOARGS, Color_copy_doc},
876  {"__copy__", (PyCFunction)Color_copy, METH_NOARGS, Color_copy_doc},
877  {"__deepcopy__", (PyCFunction)Color_deepcopy, METH_VARARGS, Color_copy_doc},
878 
879  /* base-math methods */
880  {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc},
881  {NULL, NULL, 0, NULL},
882 };
883 
884 /* ------------------PY_OBECT DEFINITION-------------------------- */
885 PyDoc_STRVAR(color_doc,
886  ".. class:: Color(rgb)\n"
887  "\n"
888  " This object gives access to Colors in Blender.\n"
889  "\n"
890  " :param rgb: (r, g, b) color values\n"
891  " :type rgb: 3d vector\n");
892 PyTypeObject color_Type = {
893  PyVarObject_HEAD_INIT(NULL, 0) "Color", /* tp_name */
894  sizeof(ColorObject), /* tp_basicsize */
895  0, /* tp_itemsize */
896  (destructor)BaseMathObject_dealloc, /* tp_dealloc */
897  (printfunc)NULL, /* tp_print */
898  NULL, /* tp_getattr */
899  NULL, /* tp_setattr */
900  NULL, /* tp_compare */
901  (reprfunc)Color_repr, /* tp_repr */
902  &Color_NumMethods, /* tp_as_number */
903  &Color_SeqMethods, /* tp_as_sequence */
904  &Color_AsMapping, /* tp_as_mapping */
905  (hashfunc)Color_hash, /* tp_hash */
906  NULL, /* tp_call */
907 #ifndef MATH_STANDALONE
908  (reprfunc)Color_str, /* tp_str */
909 #else
910  NULL, /* tp_str */
911 #endif
912  NULL, /* tp_getattro */
913  NULL, /* tp_setattro */
914  NULL, /* tp_as_buffer */
915  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
916  color_doc, /* tp_doc */
917  (traverseproc)BaseMathObject_traverse, /* tp_traverse */
918  (inquiry)BaseMathObject_clear, /* tp_clear */
919  (richcmpfunc)Color_richcmpr, /* tp_richcompare */
920  0, /* tp_weaklistoffset */
921  NULL, /* tp_iter */
922  NULL, /* tp_iternext */
923  Color_methods, /* tp_methods */
924  NULL, /* tp_members */
925  Color_getseters, /* tp_getset */
926  NULL, /* tp_base */
927  NULL, /* tp_dict */
928  NULL, /* tp_descr_get */
929  NULL, /* tp_descr_set */
930  0, /* tp_dictoffset */
931  NULL, /* tp_init */
932  NULL, /* tp_alloc */
933  Color_new, /* tp_new */
934  NULL, /* tp_free */
935  NULL, /* tp_is_gc */
936  NULL, /* tp_bases */
937  NULL, /* tp_mro */
938  NULL, /* tp_cache */
939  NULL, /* tp_subclasses */
940  NULL, /* tp_weaklist */
941  NULL, /* tp_del */
942 };
943 
944 PyObject *Color_CreatePyObject(const float col[3], PyTypeObject *base_type)
945 {
946  ColorObject *self;
947  float *col_alloc;
948 
949  col_alloc = PyMem_Malloc(COLOR_SIZE * sizeof(float));
950  if (UNLIKELY(col_alloc == NULL)) {
951  PyErr_SetString(PyExc_MemoryError,
952  "Color(): "
953  "problem allocating data");
954  return NULL;
955  }
956 
957  self = BASE_MATH_NEW(ColorObject, color_Type, base_type);
958  if (self) {
959  self->col = col_alloc;
960 
961  /* init callbacks as NULL */
962  self->cb_user = NULL;
963  self->cb_type = self->cb_subtype = 0;
964 
965  /* NEW */
966  if (col) {
967  copy_v3_v3(self->col, col);
968  }
969  else {
970  zero_v3(self->col);
971  }
972 
973  self->flag = BASE_MATH_FLAG_DEFAULT;
974  }
975  else {
976  PyMem_Free(col_alloc);
977  }
978 
979  return (PyObject *)self;
980 }
981 
982 PyObject *Color_CreatePyObject_wrap(float col[3], PyTypeObject *base_type)
983 {
984  ColorObject *self;
985 
986  self = BASE_MATH_NEW(ColorObject, color_Type, base_type);
987  if (self) {
988  /* init callbacks as NULL */
989  self->cb_user = NULL;
990  self->cb_type = self->cb_subtype = 0;
991 
992  /* WRAP */
993  self->col = col;
995  }
996 
997  return (PyObject *)self;
998 }
999 
1000 PyObject *Color_CreatePyObject_cb(PyObject *cb_user, uchar cb_type, uchar cb_subtype)
1001 {
1003  if (self) {
1004  Py_INCREF(cb_user);
1005  self->cb_user = cb_user;
1006  self->cb_type = cb_type;
1007  self->cb_subtype = cb_subtype;
1008  PyObject_GC_Track(self);
1009  }
1010 
1011  return (PyObject *)self;
1012 }
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define ATTR_FALLTHROUGH
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:71
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
double double_round(double x, int ndigits)
Definition: math_base.c:47
void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
Definition: math_color.c:68
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
Definition: math_color.c:254
void rgb_to_hsv(float r, float g, float b, float *r_h, float *r_s, float *r_v)
Definition: math_color.c:229
void sub_vn_vn(float *array_tar, const float *array_src, const int size)
Definition: math_vector.c:1312
void mul_vn_vn_fl(float *array_tar, const float *array_src, const int size, const float f)
Definition: math_vector.c:1253
void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size)
Definition: math_vector.c:1322
MINLINE void clamp_v3(float vec[3], const float min, const float max)
void add_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size)
Definition: math_vector.c:1273
MINLINE void copy_v3_v3(float r[3], const float a[3])
void add_vn_vn(float *array_tar, const float *array_src, const int size)
Definition: math_vector.c:1263
void negate_vn_vn(float *array_tar, const float *array_src, const int size)
Definition: math_vector.c:1210
MINLINE void zero_v3(float r[3])
void mul_vn_fl(float *array_tar, const int size, const float f)
Definition: math_vector.c:1244
unsigned char uchar
Definition: BLI_sys_types.h:86
#define UNUSED(x)
#define POINTER_AS_INT(i)
#define UNLIKELY(x)
#define MIN2(a, b)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Group RGB to Bright Vector Camera CLAMP
ATTR_WARN_UNUSED_RESULT const BMVert * v2
PyObject * self
Definition: bpy_driver.c:185
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
uint col
int count
PyObject * BaseMathObject_freeze(BaseMathObject *self)
Definition: mathutils.c:698
PyObject * BaseMathObject_is_frozen_get(BaseMathObject *self, void *UNUSED(closure))
Definition: mathutils.c:685
PyObject * BaseMathObject_is_wrapped_get(BaseMathObject *self, void *UNUSED(closure))
Definition: mathutils.c:678
PyObject * mathutils_dynstr_to_py(struct DynStr *ds)
Definition: mathutils.c:564
Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
Definition: mathutils.c:85
void BaseMathObject_dealloc(BaseMathObject *self)
Definition: mathutils.c:722
int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
Definition: mathutils.c:551
PyObject * BaseMathObject_owner_get(BaseMathObject *self, void *UNUSED(closure))
Definition: mathutils.c:670
char BaseMathObject_is_wrapped_doc[]
Definition: mathutils.c:676
char BaseMathObject_is_frozen_doc[]
Definition: mathutils.c:683
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
Definition: mathutils.c:118
char BaseMathObject_owner_doc[]
Definition: mathutils.c:669
char BaseMathObject_freeze_doc[]
Definition: mathutils.c:690
int BaseMathObject_clear(BaseMathObject *self)
Definition: mathutils.c:716
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
Definition: mathutils.c:710
#define BaseMath_ReadCallback_ForWrite(_self)
Definition: mathutils.h:138
#define BaseMath_ReadIndexCallback(_self, _index)
Definition: mathutils.h:132
#define BaseMath_WriteCallback(_self)
Definition: mathutils.h:130
#define BASE_MATH_NEW(struct_name, root_type, base_type)
Definition: mathutils.h:33
#define BaseMathObject_Prepare_ForHash(_self)
Definition: mathutils.h:153
@ BASE_MATH_FLAG_IS_WRAP
Definition: mathutils.h:44
#define BASE_MATH_FLAG_DEFAULT
Definition: mathutils.h:51
#define BaseMath_Prepare_ForWrite(_self)
Definition: mathutils.h:148
#define BaseMath_ReadCallback(_self)
Definition: mathutils.h:128
#define BaseMath_WriteIndexCallback(_self, _index)
Definition: mathutils.h:134
PyTypeObject color_Type
static PyObject * Color_subscript(ColorObject *self, PyObject *item)
static Py_hash_t Color_hash(ColorObject *self)
static int Color_ass_subscript(ColorObject *self, PyObject *item, PyObject *value)
static PyObject * Color_copy(ColorObject *self)
static PyObject * Color_channel_hsv_get(ColorObject *self, void *type)
static PyObject * Color_channel_get(ColorObject *self, void *type)
static PySequenceMethods Color_SeqMethods
static PyObject * Color_div(PyObject *v1, PyObject *v2)
static PyObject * Color_slice(ColorObject *self, int begin, int end)
static PyGetSetDef Color_getseters[]
static PyObject * Color_ToTupleExt(ColorObject *self, int ndigits)
static PyObject * Color_mul(PyObject *v1, PyObject *v2)
static PyObject * Color_imul(PyObject *v1, PyObject *v2)
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")
PyObject * Color_CreatePyObject_cb(PyObject *cb_user, uchar cb_type, uchar cb_subtype)
static PyObject * Color_sub(PyObject *v1, PyObject *v2)
#define COLOR_SIZE
static PyObject * Color_neg(ColorObject *self)
static PyNumberMethods Color_NumMethods
static PyObject * Color_richcmpr(PyObject *a, PyObject *b, int op)
PyObject * Color_CreatePyObject(const float col[3], PyTypeObject *base_type)
static int Color_ass_slice(ColorObject *self, int begin, int end, PyObject *seq)
PyObject * Color_CreatePyObject_wrap(float col[3], PyTypeObject *base_type)
static PyObject * Color_str(ColorObject *self)
static PyObject * Color_repr(ColorObject *self)
static int Color_hsv_set(ColorObject *self, PyObject *value, void *UNUSED(closure))
static struct PyMethodDef Color_methods[]
static PyObject * Color_iadd(PyObject *v1, PyObject *v2)
static PyObject * Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static PyMappingMethods Color_AsMapping
static PyObject * Color_add(PyObject *v1, PyObject *v2)
static PyObject * Color_item(ColorObject *self, int i)
static int Color_ass_item(ColorObject *self, int i, PyObject *value)
static PyObject * Color_idiv(PyObject *v1, PyObject *v2)
static PyObject * Color_deepcopy(ColorObject *self, PyObject *args)
static int Color_channel_set(ColorObject *self, PyObject *value, void *type)
static int Color_channel_hsv_set(ColorObject *self, PyObject *value, void *type)
static PyObject * Color_isub(PyObject *v1, PyObject *v2)
static int Color_len(ColorObject *UNUSED(self))
static PyObject * color_mul_float(ColorObject *color, const float scalar)
static PyObject * Color_hsv_get(ColorObject *self, void *UNUSED(closure))
#define ColorObject_Check(v)
static unsigned a[3]
Definition: RandGen.cpp:92
int PyC_CheckArgs_DeepCopy(PyObject *args)
#define PyTuple_SET_ITEMS(op_arg,...)
return ret