c0372a10aef933932fff8cd09ef1c826575d3263
[blender.git] / source / blender / freestyle / intern / python / BPy_StrokeAttribute.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
22  *  \ingroup freestyle
23  */
24
25 #include "BPy_StrokeAttribute.h"
26
27 #include "BPy_Convert.h"
28
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32
33 ///////////////////////////////////////////////////////////////////////////////////////////
34
35 //-------------------MODULE INITIALIZATION--------------------------------
36 int StrokeAttribute_Init(PyObject *module)
37 {
38         if (module == NULL)
39                 return -1;
40
41         if (PyType_Ready(&StrokeAttribute_Type) < 0)
42                 return -1;
43         Py_INCREF(&StrokeAttribute_Type);
44         PyModule_AddObject(module, "StrokeAttribute", (PyObject *)&StrokeAttribute_Type);
45
46         StrokeAttribute_mathutils_register_callback();
47         return 0;
48 }
49
50 //------------------------INSTANCE METHODS ----------------------------------
51
52 PyDoc_STRVAR(StrokeAttribute_doc,
53 "Class to define a set of attributes associated with a :class:`StrokeVertex`.\n"
54 "The attribute set stores the color, alpha and thickness values for a Stroke\n"
55 "Vertex.\n"
56 "\n"
57 ".. method:: __init__()\n"
58 "\n"
59 "   Default constructor.\n"
60 "\n"
61 ".. method:: __init__(brother)\n"
62 "\n"
63 "   Copy constructor.\n"
64 "\n"
65 "   :arg brother: A StrokeAttribute object.\n"
66 "   :type brother: :class:`StrokeAttribute`\n"
67 "\n"
68 ".. method:: __init__(red, green, blue, alpha, thickness_right, thickness_left)\n"
69 "\n"
70 "   Build a stroke vertex attribute from a set of parameters.\n"
71 "\n"
72 "   :arg red: Red component of a stroke color.\n"
73 "   :type red: float\n"
74 "   :arg green: Green component of a stroke color.\n"
75 "   :type green: float\n"
76 "   :arg blue: Blue component of a stroke color.\n"
77 "   :type blue: float\n"
78 "   :arg alpha: Alpha component of a stroke color.\n"
79 "   :type alpha: float\n"
80 "   :arg thickness_right: Stroke thickness on the right.\n"
81 "   :type thickness_right: float\n"
82 "   :arg thickness_left: Stroke thickness on the left.\n"
83 "   :type thickness_left: float\n"
84 "\n"
85 ".. method:: __init__(attribute1, attribute2, t)\n"
86 "\n"
87 "   Interpolation constructor. Build a StrokeAttribute from two\n"
88 "   StrokeAttribute objects and an interpolation parameter.\n"
89 "\n"
90 "   :arg attribute1: The first StrokeAttribute object.\n"
91 "   :type attribute1: :class:`StrokeAttribute`\n"
92 "   :arg attribute2: The second StrokeAttribute object.\n"
93 "   :type attribute2: :class:`StrokeAttribute`\n"
94 "   :arg t: The interpolation parameter (0 <= t <= 1).\n"
95 "   :type t: float\n");
96
97 static int StrokeAttribute_init(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
98 {
99         static const char *kwlist_1[] = {"brother", NULL};
100         static const char *kwlist_2[] = {"attribute1", "attribute2", "t", NULL};
101         static const char *kwlist_3[] = {"red", "green", "blue", "alpha", "thickness_right", "thickness_left", NULL};
102         PyObject *obj1 = 0, *obj2 = 0;
103         float red, green, blue, alpha, thickness_right, thickness_left, t;
104
105         if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &StrokeAttribute_Type, &obj1)) {
106                 if (!obj1)
107                         self->sa = new StrokeAttribute();
108                 else
109                         self->sa = new StrokeAttribute(*(((BPy_StrokeAttribute *)obj1)->sa));
110         }
111         else if (PyErr_Clear(),
112                  PyArg_ParseTupleAndKeywords(args, kwds, "O!O!f", (char **)kwlist_2,
113                                              &StrokeAttribute_Type, &obj1, &StrokeAttribute_Type, &obj2, &t))
114         {
115                 self->sa = new StrokeAttribute(*(((BPy_StrokeAttribute *)obj1)->sa), *(((BPy_StrokeAttribute *)obj2)->sa), t);
116         }
117         else if (PyErr_Clear(),
118                  PyArg_ParseTupleAndKeywords(args, kwds, "ffffff", (char **)kwlist_3,
119                                              &red, &green, &blue, &alpha, &thickness_right, &thickness_left))
120         {
121                 self->sa = new StrokeAttribute(red, green, blue, alpha, thickness_right, thickness_left);
122         }
123         else {
124                 PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
125                 return -1;
126         }
127         self->borrowed = 0;
128         return 0;
129 }
130
131 static void StrokeAttribute_dealloc(BPy_StrokeAttribute *self)
132 {
133         if (self->sa && !self->borrowed)
134                 delete self->sa;
135         Py_TYPE(self)->tp_free((PyObject *)self);
136 }
137
138 static PyObject * StrokeAttribute_repr(BPy_StrokeAttribute *self)
139 {
140         stringstream repr("StrokeAttribute:");
141         repr << " r: " << self->sa->getColorR() << " g: " << self->sa->getColorG() << " b: " << self->sa->getColorB() <<
142                 " a: " << self->sa->getAlpha() <<
143                 " - R: " << self->sa->getThicknessR()  << " L: " << self->sa->getThicknessL();
144
145         return PyUnicode_FromString(repr.str().c_str());
146 }
147
148 PyDoc_STRVAR(StrokeAttribute_get_attribute_real_doc,
149 ".. method:: get_attribute_real(name)\n"
150 "\n"
151 "   Returns an attribute of float type.\n"
152 "\n"
153 "   :arg name: The name of the attribute.\n"
154 "   :type name: str\n"
155 "   :return: The attribute value.\n"
156 "   :rtype: float\n");
157
158 static PyObject *StrokeAttribute_get_attribute_real(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
159 {
160         static const char *kwlist[] = {"name", NULL};
161         char *attr;
162
163         if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr))
164                 return NULL;
165         double a = self->sa->getAttributeReal(attr);
166         return PyFloat_FromDouble(a);
167 }
168
169 PyDoc_STRVAR(StrokeAttribute_get_attribute_vec2_doc,
170 ".. method:: get_attribute_vec2(name)\n"
171 "\n"
172 "   Returns an attribute of two-dimensional vector type.\n"
173 "\n"
174 "   :arg name: The name of the attribute.\n"
175 "   :type name: str\n"
176 "   :return: The attribute value.\n"
177 "   :rtype: :class:`mathutils.Vector`\n");
178
179 static PyObject *StrokeAttribute_get_attribute_vec2(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
180 {
181         static const char *kwlist[] = {"name", NULL};
182         char *attr;
183
184         if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr))
185                 return NULL;
186         Vec2f a = self->sa->getAttributeVec2f(attr);
187         return Vector_from_Vec2f(a);
188 }
189
190 PyDoc_STRVAR(StrokeAttribute_get_attribute_vec3_doc,
191 ".. method:: get_attribute_vec3(name)\n"
192 "\n"
193 "   Returns an attribute of three-dimensional vector type.\n"
194 "\n"
195 "   :arg name: The name of the attribute.\n"
196 "   :type name: str\n"
197 "   :return: The attribute value.\n"
198 "   :rtype: :class:`mathutils.Vector`\n");
199
200 static PyObject *StrokeAttribute_get_attribute_vec3(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
201 {
202         static const char *kwlist[] = {"name", NULL};
203         char *attr;
204
205         if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr))
206                 return NULL;
207         Vec3f a = self->sa->getAttributeVec3f(attr);
208         return Vector_from_Vec3f(a);
209 }
210
211 PyDoc_STRVAR(StrokeAttribute_has_attribute_real_doc,
212 ".. method:: has_attribute_real(name)\n"
213 "\n"
214 "   Checks whether the attribute name of float type is available.\n"
215 "\n"
216 "   :arg name: The name of the attribute.\n"
217 "   :type name: str\n"
218 "   :return: True if the attribute is availbale.\n"
219 "   :rtype: bool\n");
220
221 static PyObject *StrokeAttribute_has_attribute_real(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
222 {
223         static const char *kwlist[] = {"name", NULL};
224         char *attr;
225
226         if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr))
227                 return NULL;
228         return PyBool_from_bool(self->sa->isAttributeAvailableReal(attr));
229 }
230
231 PyDoc_STRVAR(StrokeAttribute_has_attribute_vec2_doc,
232 ".. method:: has_attribute_vec2(name)\n"
233 "\n"
234 "   Checks whether the attribute name of two-dimensional vector type\n"
235 "   is available.\n"
236 "\n"
237 "   :arg name: The name of the attribute.\n"
238 "   :type name: str\n"
239 "   :return: True if the attribute is availbale.\n"
240 "   :rtype: bool\n");
241
242 static PyObject *StrokeAttribute_has_attribute_vec2(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
243 {
244         static const char *kwlist[] = {"name", NULL};
245         char *attr;
246
247         if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr))
248                 return NULL;
249         return PyBool_from_bool(self->sa->isAttributeAvailableVec2f(attr));
250 }
251
252 PyDoc_STRVAR(StrokeAttribute_has_attribute_vec3_doc,
253 ".. method:: has_attribute_vec3(name)\n"
254 "\n"
255 "   Checks whether the attribute name of three-dimensional vector\n"
256 "   type is available.\n"
257 "\n"
258 "   :arg name: The name of the attribute.\n"
259 "   :type name: str\n"
260 "   :return: True if the attribute is availbale.\n"
261 "   :rtype: bool\n");
262
263 static PyObject *StrokeAttribute_has_attribute_vec3(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
264 {
265         static const char *kwlist[] = {"name", NULL};
266         char *attr;
267
268         if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr))
269                 return NULL;
270         return PyBool_from_bool(self->sa->isAttributeAvailableVec3f(attr));
271 }
272
273 PyDoc_STRVAR(StrokeAttribute_set_attribute_real_doc,
274 ".. method:: set_attribute_real(name, value)\n"
275 "\n"
276 "   Adds a user-defined attribute of float type.  If there is no\n"
277 "   attribute of the given name, it is added.  Otherwise, the new value\n"
278 "   replaces the old one.\n"
279 "\n"
280 "   :arg name: The name of the attribute.\n"
281 "   :type name: str\n"
282 "   :arg value: The attribute value.\n"
283 "   :type value: float\n");
284
285 static PyObject * StrokeAttribute_set_attribute_real(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
286 {
287         static const char *kwlist[] = {"name", "value", NULL};
288         char *s = 0;
289         double d = 0;
290
291         if (!PyArg_ParseTupleAndKeywords(args, kwds, "sd", (char **)kwlist, &s, &d))
292                 return NULL;
293         self->sa->setAttributeReal(s, d);
294         Py_RETURN_NONE;
295 }
296
297 PyDoc_STRVAR(StrokeAttribute_set_attribute_vec2_doc,
298 ".. method:: set_attribute_vec2(name, value)\n"
299 "\n"
300 "   Adds a user-defined attribute of two-dimensional vector type.  If\n"
301 "   there is no attribute of the given name, it is added.  Otherwise,\n"
302 "   the new value replaces the old one.\n"
303 "\n"
304 "   :arg name: The name of the attribute.\n"
305 "   :type name: str\n"
306 "   :arg value: The attribute value.\n"
307 "   :type value: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n");
308
309 static PyObject * StrokeAttribute_set_attribute_vec2(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
310 {
311         static const char *kwlist[] = {"name", "value", NULL};
312         char *s;
313         PyObject *obj = 0;
314
315         if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO", (char **)kwlist, &s, &obj))
316                 return NULL;
317         Vec2f *v = Vec2f_ptr_from_PyObject(obj);
318         if (!v) {
319                 PyErr_SetString(PyExc_TypeError, "argument 2 must be a 2D vector (either a list of 2 elements or Vector)");
320                 return NULL;
321         }
322         self->sa->setAttributeVec2f(s, *v);
323         delete v;
324         Py_RETURN_NONE;
325 }
326
327 PyDoc_STRVAR(StrokeAttribute_set_attribute_vec3_doc,
328 ".. method:: set_attribute_vec3(name, value)\n"
329 "\n"
330 "   Adds a user-defined attribute of three-dimensional vector type.\n"
331 "   If there is no attribute of the given name, it is added.\n"
332 "   Otherwise, the new value replaces the old one.\n"
333 "\n"
334 "   :arg name: The name of the attribute.\n"
335 "   :type name: str\n"
336 "   :arg value: The attribute value.\n"
337 "   :type value: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n");
338
339 static PyObject * StrokeAttribute_set_attribute_vec3(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
340 {
341         static const char *kwlist[] = {"name", "value", NULL};
342         char *s;
343         PyObject *obj = 0;
344
345         if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO", (char **)kwlist, &s, &obj))
346                 return NULL;
347         Vec3f *v = Vec3f_ptr_from_PyObject(obj);
348         if (!v) {
349                 PyErr_SetString(PyExc_TypeError, "argument 2 must be a 3D vector (either a list of 3 elements or Vector)");
350                 return NULL;
351         }
352         self->sa->setAttributeVec3f(s, *v);
353         delete v;
354         Py_RETURN_NONE;
355 }
356
357 static PyMethodDef BPy_StrokeAttribute_methods[] = {
358         {"get_attribute_real", (PyCFunction) StrokeAttribute_get_attribute_real, METH_VARARGS | METH_KEYWORDS,
359                                StrokeAttribute_get_attribute_real_doc},
360         {"get_attribute_vec2", (PyCFunction) StrokeAttribute_get_attribute_vec2, METH_VARARGS | METH_KEYWORDS,
361                                StrokeAttribute_get_attribute_vec2_doc},
362         {"get_attribute_vec3", (PyCFunction) StrokeAttribute_get_attribute_vec3, METH_VARARGS | METH_KEYWORDS,
363                                StrokeAttribute_get_attribute_vec3_doc},
364         {"has_attribute_real", (PyCFunction) StrokeAttribute_has_attribute_real, METH_VARARGS | METH_KEYWORDS,
365                                StrokeAttribute_has_attribute_real_doc},
366         {"has_attribute_vec2", (PyCFunction) StrokeAttribute_has_attribute_vec2, METH_VARARGS | METH_KEYWORDS,
367                                StrokeAttribute_has_attribute_vec2_doc},
368         {"has_attribute_vec3", (PyCFunction) StrokeAttribute_has_attribute_vec3, METH_VARARGS | METH_KEYWORDS,
369                                StrokeAttribute_has_attribute_vec3_doc},
370         {"set_attribute_real", (PyCFunction) StrokeAttribute_set_attribute_real, METH_VARARGS | METH_KEYWORDS,
371                                StrokeAttribute_set_attribute_real_doc},
372         {"set_attribute_vec2", (PyCFunction) StrokeAttribute_set_attribute_vec2, METH_VARARGS | METH_KEYWORDS,
373                                StrokeAttribute_set_attribute_vec2_doc},
374         {"set_attribute_vec3", (PyCFunction) StrokeAttribute_set_attribute_vec3, METH_VARARGS | METH_KEYWORDS,
375                                StrokeAttribute_set_attribute_vec3_doc},
376         {NULL, NULL, 0, NULL}
377 };
378
379 /*----------------------mathutils callbacks ----------------------------*/
380
381 /* subtype */
382 #define MATHUTILS_SUBTYPE_COLOR      1
383 #define MATHUTILS_SUBTYPE_THICKNESS  2
384
385 static int StrokeAttribute_mathutils_check(BaseMathObject *bmo)
386 {
387         if (!BPy_StrokeAttribute_Check(bmo->cb_user))
388                 return -1;
389         return 0;
390 }
391
392 static int StrokeAttribute_mathutils_get(BaseMathObject *bmo, int subtype)
393 {
394         BPy_StrokeAttribute *self = (BPy_StrokeAttribute *)bmo->cb_user;
395         switch (subtype) {
396         case MATHUTILS_SUBTYPE_COLOR:
397                 bmo->data[0] = self->sa->getColorR();
398                 bmo->data[1] = self->sa->getColorG();
399                 bmo->data[2] = self->sa->getColorB();
400                 break;
401         case MATHUTILS_SUBTYPE_THICKNESS:
402                 bmo->data[0] = self->sa->getThicknessR();
403                 bmo->data[1] = self->sa->getThicknessL();
404                 break;
405         default:
406                 return -1;
407         }
408         return 0;
409 }
410
411 static int StrokeAttribute_mathutils_set(BaseMathObject *bmo, int subtype)
412 {
413         BPy_StrokeAttribute *self = (BPy_StrokeAttribute *)bmo->cb_user;
414         switch (subtype) {
415         case MATHUTILS_SUBTYPE_COLOR:
416                 self->sa->setColor(bmo->data[0], bmo->data[1], bmo->data[2]);
417                 break;
418         case MATHUTILS_SUBTYPE_THICKNESS:
419                 self->sa->setThickness(bmo->data[0], bmo->data[1]);
420                 break;
421         default:
422                 return -1;
423         }
424         return 0;
425 }
426
427 static int StrokeAttribute_mathutils_get_index(BaseMathObject *bmo, int subtype, int index)
428 {
429         BPy_StrokeAttribute *self = (BPy_StrokeAttribute *)bmo->cb_user;
430         switch (subtype) {
431         case MATHUTILS_SUBTYPE_COLOR:
432                 switch (index) {
433                 case 0: bmo->data[0] = self->sa->getColorR(); break;
434                 case 1: bmo->data[1] = self->sa->getColorG(); break;
435                 case 2: bmo->data[2] = self->sa->getColorB(); break;
436                 default:
437                         return -1;
438                 }
439                 break;
440         case MATHUTILS_SUBTYPE_THICKNESS:
441                 switch (index) {
442                 case 0: bmo->data[0] = self->sa->getThicknessR(); break;
443                 case 1: bmo->data[1] = self->sa->getThicknessL(); break;
444                 default:
445                         return -1;
446                 }
447                 break;
448         default:
449                 return -1;
450         }
451         return 0;
452 }
453
454 static int StrokeAttribute_mathutils_set_index(BaseMathObject *bmo, int subtype, int index)
455 {
456         BPy_StrokeAttribute *self = (BPy_StrokeAttribute *)bmo->cb_user;
457         switch (subtype) {
458         case MATHUTILS_SUBTYPE_COLOR:
459                 {
460                         float r = (index == 0) ? bmo->data[0] : self->sa->getColorR();
461                         float g = (index == 1) ? bmo->data[1] : self->sa->getColorG();
462                         float b = (index == 2) ? bmo->data[2] : self->sa->getColorB();
463                         self->sa->setColor(r, g, b);
464                 }
465                 break;
466         case MATHUTILS_SUBTYPE_THICKNESS:
467                 {
468                         float tr = (index == 0) ? bmo->data[0] : self->sa->getThicknessR();
469                         float tl = (index == 1) ? bmo->data[1] : self->sa->getThicknessL();
470                         self->sa->setThickness(tr, tl);
471                 }
472                 break;
473         default:
474                 return -1;
475         }
476         return 0;
477 }
478
479 static Mathutils_Callback StrokeAttribute_mathutils_cb = {
480         StrokeAttribute_mathutils_check,
481         StrokeAttribute_mathutils_get,
482         StrokeAttribute_mathutils_set,
483         StrokeAttribute_mathutils_get_index,
484         StrokeAttribute_mathutils_set_index
485 };
486
487 static unsigned char StrokeAttribute_mathutils_cb_index = -1;
488
489 void StrokeAttribute_mathutils_register_callback()
490 {
491         StrokeAttribute_mathutils_cb_index = Mathutils_RegisterCallback(&StrokeAttribute_mathutils_cb);
492 }
493
494 /*----------------------StrokeAttribute get/setters ----------------------------*/
495
496 PyDoc_STRVAR(StrokeAttribute_alpha_doc,
497 "Alpha component of the stroke color.\n"
498 "\n"
499 ":type: float");
500
501 static PyObject *StrokeAttribute_alpha_get(BPy_StrokeAttribute *self, void *UNUSED(closure))
502 {
503         return PyFloat_FromDouble(self->sa->getAlpha());
504 }
505
506 static int StrokeAttribute_alpha_set(BPy_StrokeAttribute *self, PyObject *value, void *UNUSED(closure))
507 {
508         float scalar;
509         if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
510                 PyErr_SetString(PyExc_TypeError, "value must be a number");
511                 return -1;
512         }
513         self->sa->setAlpha(scalar);
514         return 0;
515 }
516
517 PyDoc_STRVAR(StrokeAttribute_color_doc,
518 "RGB components of the stroke color.\n"
519 "\n"
520 ":type: mathutils.Color");
521
522 static PyObject *StrokeAttribute_color_get(BPy_StrokeAttribute *self, void *UNUSED(closure))
523 {
524         return Color_CreatePyObject_cb((PyObject *)self, StrokeAttribute_mathutils_cb_index, MATHUTILS_SUBTYPE_COLOR);
525 }
526
527 static int StrokeAttribute_color_set(BPy_StrokeAttribute *self, PyObject *value, void *UNUSED(closure))
528 {
529         Vec3f *v = Vec3f_ptr_from_PyObject(value);
530         if (!v) {
531                 PyErr_SetString(PyExc_ValueError, "value must be a 3-dimensional vector");
532                 return -1;
533         }
534         self->sa->setColor(v->x(), v->y(), v->z());
535         return 0;
536 }
537
538 PyDoc_STRVAR(StrokeAttribute_thickness_doc,
539 "Right and left components of the stroke thickness.\n"
540 "The right (left) component is the thickness on the right (left) of the vertex\n"
541 "when following the stroke.\n"
542 "\n"
543 ":type: mathutils.Vector");
544
545 static PyObject *StrokeAttribute_thickness_get(BPy_StrokeAttribute *self, void *UNUSED(closure))
546 {
547         return Vector_CreatePyObject_cb((PyObject *)self, 2, StrokeAttribute_mathutils_cb_index,
548                                         MATHUTILS_SUBTYPE_THICKNESS);
549 }
550
551 static int StrokeAttribute_thickness_set(BPy_StrokeAttribute *self, PyObject *value, void *UNUSED(closure))
552 {
553         Vec2f *v = Vec2f_ptr_from_PyObject(value);
554         if (!v) {
555                 PyErr_SetString(PyExc_ValueError, "value must be a 2-dimensional vector");
556                 return -1;
557         }
558         self->sa->setThickness(v->x(), v->y());
559         return 0;
560 }
561
562 PyDoc_STRVAR(StrokeAttribute_visible_doc,
563 "The visibility flag.  True if the StrokeVertex is visible.\n"
564 "\n"
565 ":type: bool");
566
567 static PyObject *StrokeAttribute_visible_get(BPy_StrokeAttribute *self, void *UNUSED(closure))
568 {
569         return PyBool_from_bool(self->sa->isVisible());
570 }
571
572 static int StrokeAttribute_visible_set(BPy_StrokeAttribute *self, PyObject *value, void *UNUSED(closure))
573 {
574         if (!PyBool_Check(value)) {
575                 PyErr_SetString(PyExc_TypeError, "value must be boolean");
576                 return -1;
577         }
578         self->sa->setVisible(bool_from_PyBool(value));
579         return 0;
580 }
581
582 static PyGetSetDef BPy_StrokeAttribute_getseters[] = {
583         {(char *)"alpha", (getter)StrokeAttribute_alpha_get, (setter)StrokeAttribute_alpha_set,
584                           (char *)StrokeAttribute_alpha_doc, NULL},
585         {(char *)"color", (getter)StrokeAttribute_color_get, (setter)StrokeAttribute_color_set,
586                           (char *)StrokeAttribute_color_doc, NULL},
587         {(char *)"thickness", (getter)StrokeAttribute_thickness_get, (setter)StrokeAttribute_thickness_set,
588                               (char *)StrokeAttribute_thickness_doc, NULL},
589         {(char *)"visible", (getter)StrokeAttribute_visible_get, (setter)StrokeAttribute_visible_set,
590                             (char *)StrokeAttribute_visible_doc, NULL},
591         {NULL, NULL, NULL, NULL, NULL}  /* Sentinel */
592 };
593
594 /*-----------------------BPy_StrokeAttribute type definition ------------------------------*/
595
596 PyTypeObject StrokeAttribute_Type = {
597         PyVarObject_HEAD_INIT(NULL, 0)
598         "StrokeAttribute",              /* tp_name */
599         sizeof(BPy_StrokeAttribute),    /* tp_basicsize */
600         0,                              /* tp_itemsize */
601         (destructor)StrokeAttribute_dealloc, /* tp_dealloc */
602         0,                              /* tp_print */
603         0,                              /* tp_getattr */
604         0,                              /* tp_setattr */
605         0,                              /* tp_reserved */
606         (reprfunc)StrokeAttribute_repr, /* tp_repr */
607         0,                              /* tp_as_number */
608         0,                              /* tp_as_sequence */
609         0,                              /* tp_as_mapping */
610         0,                              /* tp_hash  */
611         0,                              /* tp_call */
612         0,                              /* tp_str */
613         0,                              /* tp_getattro */
614         0,                              /* tp_setattro */
615         0,                              /* tp_as_buffer */
616         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
617         StrokeAttribute_doc,            /* tp_doc */
618         0,                              /* tp_traverse */
619         0,                              /* tp_clear */
620         0,                              /* tp_richcompare */
621         0,                              /* tp_weaklistoffset */
622         0,                              /* tp_iter */
623         0,                              /* tp_iternext */
624         BPy_StrokeAttribute_methods,    /* tp_methods */
625         0,                              /* tp_members */
626         BPy_StrokeAttribute_getseters,  /* tp_getset */
627         0,                              /* tp_base */
628         0,                              /* tp_dict */
629         0,                              /* tp_descr_get */
630         0,                              /* tp_descr_set */
631         0,                              /* tp_dictoffset */
632         (initproc)StrokeAttribute_init, /* tp_init */
633         0,                              /* tp_alloc */
634         PyType_GenericNew,              /* tp_new */
635 };
636
637 ///////////////////////////////////////////////////////////////////////////////////////////
638
639 #ifdef __cplusplus
640 }
641 #endif