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 
17 /** \file
18  * \ingroup freestyle
19  */
20 
21 #include "BPy_FEdgeSharp.h"
22 
23 #include "../../BPy_Convert.h"
24 #include "../../Interface0D/BPy_SVertex.h"
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
30 ///////////////////////////////////////////////////////////////////////////////////////////
31 
32 /*----------------------FEdgeSharp methods ----------------------------*/
33 
34 PyDoc_STRVAR(FEdgeSharp_doc,
35              "Class hierarchy: :class:`Interface1D` > :class:`FEdge` > :class:`FEdgeSharp`\n"
36              "\n"
37              "Class defining a sharp FEdge.  A Sharp FEdge corresponds to an initial\n"
38              "edge of the input mesh.  It can be a silhouette, a crease or a border.\n"
39              "If it is a crease edge, then it is bordered by two faces of the mesh.\n"
40              "Face a lies on its right whereas Face b lies on its left.  If it is a\n"
41              "border edge, then it doesn't have any face on its right, and thus Face\n"
42              "a is None.\n"
43              "\n"
44              ".. method:: __init__()\n"
45              "            __init__(brother)\n"
46              "            __init__(first_vertex, second_vertex)\n"
47              "\n"
48              "   Builds an :class:`FEdgeSharp` using the default constructor,\n"
49              "   copy constructor, or between two :class:`SVertex` objects.\n"
50              "\n"
51              "   :arg brother: An FEdgeSharp object.\n"
52              "   :type brother: :class:`FEdgeSharp`\n"
53              "   :arg first_vertex: The first SVertex object.\n"
54              "   :type first_vertex: :class:`SVertex`\n"
55              "   :arg second_vertex: The second SVertex object.\n"
56              "   :type second_vertex: :class:`SVertex`");
57 
FEdgeSharp_init(BPy_FEdgeSharp * self,PyObject * args,PyObject * kwds)58 static int FEdgeSharp_init(BPy_FEdgeSharp *self, PyObject *args, PyObject *kwds)
59 {
60   static const char *kwlist_1[] = {"brother", NULL};
61   static const char *kwlist_2[] = {"first_vertex", "second_vertex", NULL};
62   PyObject *obj1 = 0, *obj2 = 0;
63 
64   if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &FEdgeSharp_Type, &obj1)) {
65     if (!obj1) {
66       self->fes = new FEdgeSharp();
67     }
68     else {
69       self->fes = new FEdgeSharp(*(((BPy_FEdgeSharp *)obj1)->fes));
70     }
71   }
72   else if ((void)PyErr_Clear(),
73            PyArg_ParseTupleAndKeywords(args,
74                                        kwds,
75                                        "O!O!",
76                                        (char **)kwlist_2,
77                                        &SVertex_Type,
78                                        &obj1,
79                                        &SVertex_Type,
80                                        &obj2)) {
81     self->fes = new FEdgeSharp(((BPy_SVertex *)obj1)->sv, ((BPy_SVertex *)obj2)->sv);
82   }
83   else {
84     PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
85     return -1;
86   }
87   self->py_fe.fe = self->fes;
88   self->py_fe.py_if1D.if1D = self->fes;
89   self->py_fe.py_if1D.borrowed = false;
90   return 0;
91 }
92 
93 /*----------------------mathutils callbacks ----------------------------*/
94 
95 /* subtype */
96 #define MATHUTILS_SUBTYPE_NORMAL_A 1
97 #define MATHUTILS_SUBTYPE_NORMAL_B 2
98 
FEdgeSharp_mathutils_check(BaseMathObject * bmo)99 static int FEdgeSharp_mathutils_check(BaseMathObject *bmo)
100 {
101   if (!BPy_FEdgeSharp_Check(bmo->cb_user)) {
102     return -1;
103   }
104   return 0;
105 }
106 
FEdgeSharp_mathutils_get(BaseMathObject * bmo,int subtype)107 static int FEdgeSharp_mathutils_get(BaseMathObject *bmo, int subtype)
108 {
109   BPy_FEdgeSharp *self = (BPy_FEdgeSharp *)bmo->cb_user;
110   switch (subtype) {
111     case MATHUTILS_SUBTYPE_NORMAL_A: {
112       Vec3r p(self->fes->normalA());
113       bmo->data[0] = p[0];
114       bmo->data[1] = p[1];
115       bmo->data[2] = p[2];
116     } break;
117     case MATHUTILS_SUBTYPE_NORMAL_B: {
118       Vec3r p(self->fes->normalB());
119       bmo->data[0] = p[0];
120       bmo->data[1] = p[1];
121       bmo->data[2] = p[2];
122     } break;
123     default:
124       return -1;
125   }
126   return 0;
127 }
128 
FEdgeSharp_mathutils_set(BaseMathObject * bmo,int subtype)129 static int FEdgeSharp_mathutils_set(BaseMathObject *bmo, int subtype)
130 {
131   BPy_FEdgeSharp *self = (BPy_FEdgeSharp *)bmo->cb_user;
132   switch (subtype) {
133     case MATHUTILS_SUBTYPE_NORMAL_A: {
134       Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
135       self->fes->setNormalA(p);
136     } break;
137     case MATHUTILS_SUBTYPE_NORMAL_B: {
138       Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
139       self->fes->setNormalB(p);
140     } break;
141     default:
142       return -1;
143   }
144   return 0;
145 }
146 
FEdgeSharp_mathutils_get_index(BaseMathObject * bmo,int subtype,int index)147 static int FEdgeSharp_mathutils_get_index(BaseMathObject *bmo, int subtype, int index)
148 {
149   BPy_FEdgeSharp *self = (BPy_FEdgeSharp *)bmo->cb_user;
150   switch (subtype) {
151     case MATHUTILS_SUBTYPE_NORMAL_A: {
152       Vec3r p(self->fes->normalA());
153       bmo->data[index] = p[index];
154     } break;
155     case MATHUTILS_SUBTYPE_NORMAL_B: {
156       Vec3r p(self->fes->normalB());
157       bmo->data[index] = p[index];
158     } break;
159     default:
160       return -1;
161   }
162   return 0;
163 }
164 
FEdgeSharp_mathutils_set_index(BaseMathObject * bmo,int subtype,int index)165 static int FEdgeSharp_mathutils_set_index(BaseMathObject *bmo, int subtype, int index)
166 {
167   BPy_FEdgeSharp *self = (BPy_FEdgeSharp *)bmo->cb_user;
168   switch (subtype) {
169     case MATHUTILS_SUBTYPE_NORMAL_A: {
170       Vec3r p(self->fes->normalA());
171       p[index] = bmo->data[index];
172       self->fes->setNormalA(p);
173     } break;
174     case MATHUTILS_SUBTYPE_NORMAL_B: {
175       Vec3r p(self->fes->normalB());
176       p[index] = bmo->data[index];
177       self->fes->setNormalB(p);
178     } break;
179     default:
180       return -1;
181   }
182   return 0;
183 }
184 
185 static Mathutils_Callback FEdgeSharp_mathutils_cb = {
186     FEdgeSharp_mathutils_check,
187     FEdgeSharp_mathutils_get,
188     FEdgeSharp_mathutils_set,
189     FEdgeSharp_mathutils_get_index,
190     FEdgeSharp_mathutils_set_index,
191 };
192 
193 static unsigned char FEdgeSharp_mathutils_cb_index = -1;
194 
FEdgeSharp_mathutils_register_callback()195 void FEdgeSharp_mathutils_register_callback()
196 {
197   FEdgeSharp_mathutils_cb_index = Mathutils_RegisterCallback(&FEdgeSharp_mathutils_cb);
198 }
199 
200 /*----------------------FEdgeSharp get/setters ----------------------------*/
201 
202 PyDoc_STRVAR(FEdgeSharp_normal_right_doc,
203              "The normal to the face lying on the right of the FEdge.  If this FEdge\n"
204              "is a border, it has no Face on its right and therefore no normal.\n"
205              "\n"
206              ":type: :class:`mathutils.Vector`");
207 
FEdgeSharp_normal_right_get(BPy_FEdgeSharp * self,void * UNUSED (closure))208 static PyObject *FEdgeSharp_normal_right_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
209 {
210   return Vector_CreatePyObject_cb(
211       (PyObject *)self, 3, FEdgeSharp_mathutils_cb_index, MATHUTILS_SUBTYPE_NORMAL_A);
212 }
213 
FEdgeSharp_normal_right_set(BPy_FEdgeSharp * self,PyObject * value,void * UNUSED (closure))214 static int FEdgeSharp_normal_right_set(BPy_FEdgeSharp *self,
215                                        PyObject *value,
216                                        void *UNUSED(closure))
217 {
218   float v[3];
219   if (mathutils_array_parse(v, 3, 3, value, "value must be a 3-dimensional vector") == -1) {
220     return -1;
221   }
222   Vec3r p(v[0], v[1], v[2]);
223   self->fes->setNormalA(p);
224   return 0;
225 }
226 
227 PyDoc_STRVAR(FEdgeSharp_normal_left_doc,
228              "The normal to the face lying on the left of the FEdge.\n"
229              "\n"
230              ":type: :class:`mathutils.Vector`");
231 
FEdgeSharp_normal_left_get(BPy_FEdgeSharp * self,void * UNUSED (closure))232 static PyObject *FEdgeSharp_normal_left_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
233 {
234   return Vector_CreatePyObject_cb(
235       (PyObject *)self, 3, FEdgeSharp_mathutils_cb_index, MATHUTILS_SUBTYPE_NORMAL_B);
236 }
237 
FEdgeSharp_normal_left_set(BPy_FEdgeSharp * self,PyObject * value,void * UNUSED (closure))238 static int FEdgeSharp_normal_left_set(BPy_FEdgeSharp *self, PyObject *value, void *UNUSED(closure))
239 {
240   float v[3];
241   if (mathutils_array_parse(v, 3, 3, value, "value must be a 3-dimensional vector") == -1) {
242     return -1;
243   }
244   Vec3r p(v[0], v[1], v[2]);
245   self->fes->setNormalB(p);
246   return 0;
247 }
248 
249 PyDoc_STRVAR(FEdgeSharp_material_index_right_doc,
250              "The index of the material of the face lying on the right of the FEdge.\n"
251              "If this FEdge is a border, it has no Face on its right and therefore\n"
252              "no material.\n"
253              "\n"
254              ":type: int");
255 
FEdgeSharp_material_index_right_get(BPy_FEdgeSharp * self,void * UNUSED (closure))256 static PyObject *FEdgeSharp_material_index_right_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
257 {
258   return PyLong_FromLong(self->fes->aFrsMaterialIndex());
259 }
260 
FEdgeSharp_material_index_right_set(BPy_FEdgeSharp * self,PyObject * value,void * UNUSED (closure))261 static int FEdgeSharp_material_index_right_set(BPy_FEdgeSharp *self,
262                                                PyObject *value,
263                                                void *UNUSED(closure))
264 {
265   unsigned int i = PyLong_AsUnsignedLong(value);
266   if (PyErr_Occurred()) {
267     return -1;
268   }
269   self->fes->setaFrsMaterialIndex(i);
270   return 0;
271 }
272 
273 PyDoc_STRVAR(FEdgeSharp_material_index_left_doc,
274              "The index of the material of the face lying on the left of the FEdge.\n"
275              "\n"
276              ":type: int");
277 
FEdgeSharp_material_index_left_get(BPy_FEdgeSharp * self,void * UNUSED (closure))278 static PyObject *FEdgeSharp_material_index_left_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
279 {
280   return PyLong_FromLong(self->fes->bFrsMaterialIndex());
281 }
282 
FEdgeSharp_material_index_left_set(BPy_FEdgeSharp * self,PyObject * value,void * UNUSED (closure))283 static int FEdgeSharp_material_index_left_set(BPy_FEdgeSharp *self,
284                                               PyObject *value,
285                                               void *UNUSED(closure))
286 {
287   unsigned int i = PyLong_AsUnsignedLong(value);
288   if (PyErr_Occurred()) {
289     return -1;
290   }
291   self->fes->setbFrsMaterialIndex(i);
292   return 0;
293 }
294 
295 PyDoc_STRVAR(FEdgeSharp_material_right_doc,
296              "The material of the face lying on the right of the FEdge.  If this FEdge\n"
297              "is a border, it has no Face on its right and therefore no material.\n"
298              "\n"
299              ":type: :class:`Material`");
300 
FEdgeSharp_material_right_get(BPy_FEdgeSharp * self,void * UNUSED (closure))301 static PyObject *FEdgeSharp_material_right_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
302 {
303   return BPy_FrsMaterial_from_FrsMaterial(self->fes->aFrsMaterial());
304 }
305 
306 PyDoc_STRVAR(FEdgeSharp_material_left_doc,
307              "The material of the face lying on the left of the FEdge.\n"
308              "\n"
309              ":type: :class:`Material`");
310 
FEdgeSharp_material_left_get(BPy_FEdgeSharp * self,void * UNUSED (closure))311 static PyObject *FEdgeSharp_material_left_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
312 {
313   return BPy_FrsMaterial_from_FrsMaterial(self->fes->bFrsMaterial());
314 }
315 
316 PyDoc_STRVAR(FEdgeSharp_face_mark_right_doc,
317              "The face mark of the face lying on the right of the FEdge.  If this FEdge\n"
318              "is a border, it has no face on the right and thus this property is set to\n"
319              "false.\n"
320              "\n"
321              ":type: bool");
322 
FEdgeSharp_face_mark_right_get(BPy_FEdgeSharp * self,void * UNUSED (closure))323 static PyObject *FEdgeSharp_face_mark_right_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
324 {
325   return PyBool_from_bool(self->fes->aFaceMark());
326 }
327 
FEdgeSharp_face_mark_right_set(BPy_FEdgeSharp * self,PyObject * value,void * UNUSED (closure))328 static int FEdgeSharp_face_mark_right_set(BPy_FEdgeSharp *self,
329                                           PyObject *value,
330                                           void *UNUSED(closure))
331 {
332   if (!PyBool_Check(value)) {
333     return -1;
334   }
335   self->fes->setaFaceMark(bool_from_PyBool(value));
336   return 0;
337 }
338 
339 PyDoc_STRVAR(FEdgeSharp_face_mark_left_doc,
340              "The face mark of the face lying on the left of the FEdge.\n"
341              "\n"
342              ":type: bool");
343 
FEdgeSharp_face_mark_left_get(BPy_FEdgeSharp * self,void * UNUSED (closure))344 static PyObject *FEdgeSharp_face_mark_left_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
345 {
346   return PyBool_from_bool(self->fes->bFaceMark());
347 }
348 
FEdgeSharp_face_mark_left_set(BPy_FEdgeSharp * self,PyObject * value,void * UNUSED (closure))349 static int FEdgeSharp_face_mark_left_set(BPy_FEdgeSharp *self,
350                                          PyObject *value,
351                                          void *UNUSED(closure))
352 {
353   if (!PyBool_Check(value)) {
354     return -1;
355   }
356   self->fes->setbFaceMark(bool_from_PyBool(value));
357   return 0;
358 }
359 
360 static PyGetSetDef BPy_FEdgeSharp_getseters[] = {
361     {"normal_right",
362      (getter)FEdgeSharp_normal_right_get,
363      (setter)FEdgeSharp_normal_right_set,
364      FEdgeSharp_normal_right_doc,
365      NULL},
366     {"normal_left",
367      (getter)FEdgeSharp_normal_left_get,
368      (setter)FEdgeSharp_normal_left_set,
369      FEdgeSharp_normal_left_doc,
370      NULL},
371     {"material_index_right",
372      (getter)FEdgeSharp_material_index_right_get,
373      (setter)FEdgeSharp_material_index_right_set,
374      FEdgeSharp_material_index_right_doc,
375      NULL},
376     {"material_index_left",
377      (getter)FEdgeSharp_material_index_left_get,
378      (setter)FEdgeSharp_material_index_left_set,
379      FEdgeSharp_material_index_left_doc,
380      NULL},
381     {"material_right",
382      (getter)FEdgeSharp_material_right_get,
383      (setter)NULL,
384      FEdgeSharp_material_right_doc,
385      NULL},
386     {"material_left",
387      (getter)FEdgeSharp_material_left_get,
388      (setter)NULL,
389      FEdgeSharp_material_left_doc,
390      NULL},
391     {"face_mark_right",
392      (getter)FEdgeSharp_face_mark_right_get,
393      (setter)FEdgeSharp_face_mark_right_set,
394      FEdgeSharp_face_mark_right_doc,
395      NULL},
396     {"face_mark_left",
397      (getter)FEdgeSharp_face_mark_left_get,
398      (setter)FEdgeSharp_face_mark_left_set,
399      FEdgeSharp_face_mark_left_doc,
400      NULL},
401     {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
402 };
403 
404 /*-----------------------BPy_FEdgeSharp type definition ------------------------------*/
405 
406 PyTypeObject FEdgeSharp_Type = {
407     PyVarObject_HEAD_INIT(NULL, 0) "FEdgeSharp", /* tp_name */
408     sizeof(BPy_FEdgeSharp),                      /* tp_basicsize */
409     0,                                           /* tp_itemsize */
410     0,                                           /* tp_dealloc */
411     0,                                           /* tp_print */
412     0,                                           /* tp_getattr */
413     0,                                           /* tp_setattr */
414     0,                                           /* tp_reserved */
415     0,                                           /* tp_repr */
416     0,                                           /* tp_as_number */
417     0,                                           /* tp_as_sequence */
418     0,                                           /* tp_as_mapping */
419     0,                                           /* tp_hash  */
420     0,                                           /* tp_call */
421     0,                                           /* tp_str */
422     0,                                           /* tp_getattro */
423     0,                                           /* tp_setattro */
424     0,                                           /* tp_as_buffer */
425     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,    /* tp_flags */
426     FEdgeSharp_doc,                              /* tp_doc */
427     0,                                           /* tp_traverse */
428     0,                                           /* tp_clear */
429     0,                                           /* tp_richcompare */
430     0,                                           /* tp_weaklistoffset */
431     0,                                           /* tp_iter */
432     0,                                           /* tp_iternext */
433     0,                                           /* tp_methods */
434     0,                                           /* tp_members */
435     BPy_FEdgeSharp_getseters,                    /* tp_getset */
436     &FEdge_Type,                                 /* tp_base */
437     0,                                           /* tp_dict */
438     0,                                           /* tp_descr_get */
439     0,                                           /* tp_descr_set */
440     0,                                           /* tp_dictoffset */
441     (initproc)FEdgeSharp_init,                   /* tp_init */
442     0,                                           /* tp_alloc */
443     0,                                           /* tp_new */
444 };
445 
446 ///////////////////////////////////////////////////////////////////////////////////////////
447 
448 #ifdef __cplusplus
449 }
450 #endif
451