Fix for Freestyle rendering errors with color blend modes SOFT_LIGHT and LINEAR_LIGHT.
[blender.git] / source / blender / freestyle / intern / python / BPy_Freestyle.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_Freestyle.cpp
22  *  \ingroup freestyle
23  */
24
25 #include "BPy_Freestyle.h"
26
27 #include "BPy_BBox.h"
28 #include "BPy_BinaryPredicate0D.h"
29 #include "BPy_BinaryPredicate1D.h"
30 #include "BPy_ContextFunctions.h"
31 #include "BPy_Convert.h"
32 #include "BPy_FrsMaterial.h"
33 #include "BPy_FrsNoise.h"
34 #include "BPy_Id.h"
35 #include "BPy_IntegrationType.h"
36 #include "BPy_Interface0D.h"
37 #include "BPy_Interface1D.h"
38 #include "BPy_Iterator.h"
39 #include "BPy_MediumType.h"
40 #include "BPy_Nature.h"
41 #include "BPy_Operators.h"
42 #include "BPy_SShape.h"
43 #include "BPy_StrokeAttribute.h"
44 #include "BPy_StrokeShader.h"
45 #include "BPy_UnaryFunction0D.h"
46 #include "BPy_UnaryFunction1D.h"
47 #include "BPy_UnaryPredicate0D.h"
48 #include "BPy_UnaryPredicate1D.h"
49 #include "BPy_ViewMap.h"
50 #include "BPy_ViewShape.h"
51
52
53 #ifdef __cplusplus
54 extern "C" {
55 #endif
56
57 ///////////////////////////////////////////////////////////////////////////////////////////
58
59 //------------------------ MODULE FUNCTIONS ----------------------------------
60
61 #include "FRS_freestyle.h"
62 #include "RNA_access.h"
63 #include "bpy_rna.h" /* pyrna_struct_CreatePyObject() */
64
65 static char Freestyle_getCurrentScene___doc__[] =
66 ".. function:: getCurrentScene()\n"
67 "\n"
68 "   Returns the current scene.\n"
69 "\n"
70 "   :return: The current scene.\n"
71 "   :rtype: :class:`bpy.types.Scene`\n";
72
73 static PyObject *Freestyle_getCurrentScene(PyObject *self)
74 {
75         if (!freestyle_scene) {
76                 PyErr_SetString(PyExc_TypeError, "current scene not available");
77                 return NULL;
78         }
79         PointerRNA ptr_scene;
80         RNA_pointer_create(NULL, &RNA_Scene, freestyle_scene, &ptr_scene);
81         return pyrna_struct_CreatePyObject(&ptr_scene);
82 }
83
84 #include "DNA_material_types.h"
85
86 static int ramp_blend_type(const char *type)
87 {
88         if (!strcmp(type, "MIX"))           return MA_RAMP_BLEND;
89         if (!strcmp(type, "ADD"))           return MA_RAMP_ADD;
90         if (!strcmp(type, "MULTIPLY"))      return MA_RAMP_MULT;
91         if (!strcmp(type, "SUBTRACT"))      return MA_RAMP_SUB;
92         if (!strcmp(type, "SCREEN"))        return MA_RAMP_SCREEN;
93         if (!strcmp(type, "DIVIDE"))        return MA_RAMP_DIV;
94         if (!strcmp(type, "DIFFERENCE"))    return MA_RAMP_DIFF;
95         if (!strcmp(type, "DARKEN"))        return MA_RAMP_DARK;
96         if (!strcmp(type, "LIGHTEN"))       return MA_RAMP_LIGHT;
97         if (!strcmp(type, "OVERLAY"))       return MA_RAMP_OVERLAY;
98         if (!strcmp(type, "DODGE"))         return MA_RAMP_DODGE;
99         if (!strcmp(type, "BURN"))          return MA_RAMP_BURN;
100         if (!strcmp(type, "HUE"))           return MA_RAMP_HUE;
101         if (!strcmp(type, "SATURATION"))    return MA_RAMP_SAT;
102         if (!strcmp(type, "VALUE"))         return MA_RAMP_VAL;
103         if (!strcmp(type, "COLOR"))         return MA_RAMP_COLOR;
104         if (!strcmp(type, "SOFT_LIGHT"))    return MA_RAMP_SOFT;
105         if (!strcmp(type, "LINEAR_LIGHT"))  return MA_RAMP_LINEAR;
106         return -1;
107 }
108
109 #include "BKE_material.h" /* ramp_blend() */
110
111 static char Freestyle_blendRamp___doc__[] =
112 ".. function:: blendRamp(type, color1, fac, color2)\n"
113 "\n"
114 "   Blend two colors according to a ramp blend type.\n"
115 "\n"
116 "   :arg type: Ramp blend type.\n"
117 "   :type type: int\n"
118 "   :arg color1: 1st color.\n"
119 "   :type color1: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
120 "   :arg fac: Blend factor.\n"
121 "   :type fac: float\n"
122 "   :arg color2: 1st color.\n"
123 "   :type color2: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
124 "   :return: Blended color in RGB format.\n"
125 "   :rtype: :class:`mathutils.Vector`\n";
126
127 static PyObject *Freestyle_blendRamp(PyObject *self, PyObject *args)
128 {
129         PyObject *obj1, *obj2;
130         char *s;
131         int type;
132         Vec3f *v1 = NULL, *v2 = NULL;
133         float a[3], fac, b[3];
134
135         if (!PyArg_ParseTuple(args, "sOfO", &s, &obj1, &fac, &obj2))
136                 return NULL;
137         type = ramp_blend_type(s);
138         if (type < 0) {
139                 PyErr_SetString(PyExc_TypeError, "argument 1 is an unknown ramp blend type");
140                 goto error;
141         }
142         v1 = Vec3f_ptr_from_PyObject(obj1);
143         if (!v1) {
144                 PyErr_SetString(PyExc_TypeError,
145                                 "argument 2 must be a 3D vector (either a tuple/list of 3 elements or Vector)");
146                 goto error;
147         }
148         v2 = Vec3f_ptr_from_PyObject(obj2);
149         if (!v2) {
150                 PyErr_SetString(PyExc_TypeError,
151                                 "argument 4 must be a 3D vector (either a tuple/list of 3 elements or Vector)");
152                 goto error;
153         }
154         a[0] = v1->x(); b[0] = v2->x();
155         a[1] = v1->y(); b[1] = v2->y();
156         a[2] = v1->z(); b[2] = v2->z();
157         ramp_blend(type, a, fac, b);
158         delete v1;
159         delete v2;
160         return Vector_CreatePyObject(a, 3, Py_NEW, NULL);
161
162 error:
163         if (v1) delete v1;
164         if (v2) delete v2;
165         return NULL;
166 }
167
168 #include "BKE_texture.h" /* do_colorband() */
169
170 static char Freestyle_evaluateColorRamp___doc__[] =
171 ".. function:: evaluateColorRamp(ramp, in)\n"
172 "\n"
173 "   Evaluate a color ramp at a point in the interval 0 to 1.\n"
174 "\n"
175 "   :arg ramp: Color ramp object.\n"
176 "   :type ramp: :class:`bpy.types.ColorRamp`\n"
177 "   :arg in: Value in the interval 0 to 1.\n"
178 "   :type in: float\n"
179 "   :return: color in RGBA format.\n"
180 "   :rtype: :class:`mathutils.Vector`\n";
181
182 static PyObject *Freestyle_evaluateColorRamp(PyObject *self, PyObject *args)
183 {
184         BPy_StructRNA *py_srna;
185         ColorBand *coba;
186         float in, out[4];
187
188         if (!(PyArg_ParseTuple(args, "O!f", &pyrna_struct_Type, &py_srna, &in)))
189                 return NULL;
190         if (!RNA_struct_is_a(py_srna->ptr.type, &RNA_ColorRamp)) {
191                 PyErr_SetString(PyExc_TypeError, "1st argument is not a ColorRamp object");
192                 return NULL;
193         }
194         coba = (ColorBand *)py_srna->ptr.data;
195         if (!do_colorband(coba, in, out)) {
196                 PyErr_SetString(PyExc_ValueError, "failed to evaluate the color ramp");
197                 return NULL;
198         }
199         return Vector_CreatePyObject(out, 4, Py_NEW, NULL);
200 }
201
202 #include "DNA_color_types.h"
203 #include "BKE_colortools.h" /* curvemapping_evaluateF() */
204
205 static char Freestyle_evaluateCurveMappingF___doc__[] =
206 ".. function:: evaluateCurveMappingF(cumap, cur, value)\n"
207 "\n"
208 "   Evaluate a curve mapping at a point in the interval 0 to 1.\n"
209 "\n"
210 "   :arg cumap: Curve mapping object.\n"
211 "   :type cumap: :class:`bpy.types.CurveMapping`\n"
212 "   :arg cur: Index of the curve to be used (0 <= cur <= 3).\n"
213 "   :type cur: int\n"
214 "   :arg value: Input value in the interval 0 to 1.\n"
215 "   :type value: float\n"
216 "   :return: Mapped output value.\n"
217 "   :rtype: float\n";
218
219 static PyObject *Freestyle_evaluateCurveMappingF(PyObject *self, PyObject *args)
220 {
221         BPy_StructRNA *py_srna;
222         CurveMapping *cumap;
223         int cur;
224         float value;
225
226         if (!(PyArg_ParseTuple(args, "O!if", &pyrna_struct_Type, &py_srna, &cur, &value)))
227                 return NULL;
228         if (!RNA_struct_is_a(py_srna->ptr.type, &RNA_CurveMapping)) {
229                 PyErr_SetString(PyExc_TypeError, "1st argument is not a CurveMapping object");
230                 return NULL;
231         }
232         if (cur < 0 || cur > 3) {
233                 PyErr_SetString(PyExc_ValueError, "2nd argument is out of range");
234                 return NULL;
235         }
236         cumap = (CurveMapping *)py_srna->ptr.data;
237         curvemapping_initialize(cumap);
238         /* disable extrapolation if enabled */
239         if ((cumap->cm[cur].flag & CUMA_EXTEND_EXTRAPOLATE)) {
240                 cumap->cm[cur].flag &= ~(CUMA_EXTEND_EXTRAPOLATE);
241                 curvemapping_changed(cumap, 0);
242         }
243         return PyFloat_FromDouble(curvemapping_evaluateF(cumap, cur, value));
244 }
245
246 /*-----------------------Freestyle module docstring----------------------------*/
247
248 static char module_docstring[] =
249 "This module provides classes for defining line drawing rules (such as\n"
250 "predicates, functions, chaining iterators, and stroke shaders), as well\n"
251 "as helper functions for style module writing.\n"
252 "\n"
253 "Class hierarchy:\n"
254 "\n"
255 "- :class:`BBox`\n"
256 "- :class:`BinaryPredicate0D`\n"
257 "- :class:`BinaryPredicate1D`\n"
258 "\n"
259 "  - :class:`FalseBP1D`\n"
260 "  - :class:`Length2DBP1D`\n"
261 "  - :class:`SameShapeIdBP1D`\n"
262 "  - :class:`TrueBP1D`\n"
263 "  - :class:`ViewMapGradientNormBP1D`\n"
264 "\n"
265 "- :class:`Id`\n"
266 "- :class:`Interface0D`\n"
267 "\n"
268 "  - :class:`CurvePoint`\n"
269 "\n"
270 "    - :class:`StrokeVertex`\n"
271 "\n"
272 "  - :class:`SVertex`\n"
273 "  - :class:`ViewVertex`\n"
274 "\n"
275 "    - :class:`NonTVertex`\n"
276 "    - :class:`TVertex`\n"
277 "\n"
278 "- :class:`Interface1D`\n"
279 "\n"
280 "  - :class:`Curve`\n"
281 "\n"
282 "    - :class:`Chain`\n"
283 "\n"
284 "  - :class:`FEdge`\n"
285 "\n"
286 "    - :class:`FEdgeSharp`\n"
287 "    - :class:`FEdgeSmooth`\n"
288 "\n"
289 "  - :class:`Stroke`\n"
290 "  - :class:`ViewEdge`\n"
291 "\n"
292 "- :class:`Iterator`\n"
293 "\n"
294 "  - :class:`AdjacencyIterator`\n"
295 "  - :class:`CurvePointIterator`\n"
296 "  - :class:`Interface0DIterator`\n"
297 "  - :class:`SVertexIterator`\n"
298 "  - :class:`StrokeVertexIterator`\n"
299 "  - :class:`ViewEdgeIterator`\n"
300 "\n"
301 "    - :class:`ChainingIterator`\n"
302 "\n"
303 "      - :class:`ChainPredicateIterator`\n"
304 "      - :class:`ChainSilhouetteIterator`\n"
305 "\n"
306 "  - :class:`orientedViewEdgeIterator`\n"
307 "\n"
308 "- :class:`Material`\n"
309 "- :class:`Noise`\n"
310 "- :class:`Operators`\n"
311 "- :class:`SShape`\n"
312 "- :class:`StrokeAttribute`\n"
313 "- :class:`StrokeShader`\n"
314 "\n"
315 "  - :class:`BackboneStretcherShader`\n"
316 "  - :class:`BezierCurveShader`\n"
317 "  - :class:`CalligraphicShader`\n"
318 "  - :class:`ColorNoiseShader`\n"
319 "  - :class:`ColorVariationPatternShader`\n"
320 "  - :class:`ConstantColorShader`\n"
321 "  - :class:`ConstantThicknessShader`\n"
322 "  - :class:`ConstrainedIncreasingThicknessShader`\n"
323 "  - :class:`GuidingLinesShader`\n"
324 "  - :class:`IncreasingColorShader`\n"
325 "  - :class:`IncreasingThicknessShader`\n"
326 "  - :class:`PolygonalizationShader`\n"
327 "  - :class:`SamplingShader`\n"
328 "  - :class:`SmoothingShader`\n"
329 "  - :class:`SpatialNoiseShader`\n"
330 "  - :class:`StrokeTextureShader`\n"
331 "  - :class:`TextureAssignerShader`\n"
332 "  - :class:`ThicknessNoiseShader`\n"
333 "  - :class:`ThicknessVariationPatternShader`\n"
334 "  - :class:`TipRemoverShader`\n"
335 "  - :class:`fstreamShader`\n"
336 "  - :class:`streamShader`\n"
337 "\n"
338 "- :class:`UnaryFunction0D`\n"
339 "\n"
340 "  - :class:`UnaryFunction0DDouble`\n"
341 "\n"
342 "    - :class:`Curvature2DAngleF0D`\n"
343 "    - :class:`DensityF0D`\n"
344 "    - :class:`GetProjectedXF0D`\n"
345 "    - :class:`GetProjectedYF0D`\n"
346 "    - :class:`GetProjectedZF0D`\n"
347 "    - :class:`GetXF0D`\n"
348 "    - :class:`GetYF0D`\n"
349 "    - :class:`GetZF0D`\n"
350 "    - :class:`LocalAverageDepthF0D`\n"
351 "    - :class:`ZDiscontinuityF0D`\n"
352 "\n"
353 "  - :class:`UnaryFunction0DEdgeNature`\n"
354 "\n"
355 "    - :class:`CurveNatureF0D`\n"
356 "\n"
357 "  - :class:`UnaryFunction0DFloat`\n"
358 "\n"
359 "    - :class:`GetCurvilinearAbscissaF0D`\n"
360 "    - :class:`GetParameterF0D`\n"
361 "    - :class:`GetViewMapGradientNormF0D`\n"
362 "    - :class:`ReadCompleteViewMapPixelF0D`\n"
363 "    - :class:`ReadMapPixelF0D`\n"
364 "    - :class:`ReadSteerableViewMapPixelF0D`\n"
365 "\n"
366 "  - :class:`UnaryFunction0DId`\n"
367 "\n"
368 "    - :class:`ShapeIdF0D`\n"
369 "\n"
370 "  - :class:`UnaryFunction0DMaterial`\n"
371 "\n"
372 "    - :class:`MaterialF0D`\n"
373 "\n"
374 "  - :class:`UnaryFunction0DUnsigned`\n"
375 "\n"
376 "    - :class:`QuantitativeInvisibilityF0D`\n"
377 "\n"
378 "  - :class:`UnaryFunction0DVec2f`\n"
379 "\n"
380 "    - :class:`Normal2DF0D`\n"
381 "    - :class:`VertexOrientation2DF0D`\n"
382 "\n"
383 "  - :class:`UnaryFunction0DVec3f`\n"
384 "\n"
385 "    - :class:`VertexOrientation3DF0D`\n"
386 "\n"
387 "  - :class:`UnaryFunction0DVectorViewShape`\n"
388 "\n"
389 "    - :class:`GetOccludersF0D`\n"
390 "\n"
391 "  - :class:`UnaryFunction0DViewShape`\n"
392 "\n"
393 "    - :class:`GetOccludeeF0D`\n"
394 "    - :class:`GetShapeF0D`\n"
395 "\n"
396 "- :class:`UnaryFunction1D`\n"
397 "\n"
398 "  - :class:`UnaryFunction1DDouble`\n"
399 "\n"
400 "    - :class:`Curvature2DAngleF1D`\n"
401 "    - :class:`DensityF1D`\n"
402 "    - :class:`GetCompleteViewMapDensityF1D`\n"
403 "    - :class:`GetDirectionalViewMapDensityF1D`\n"
404 "    - :class:`GetProjectedXF1D`\n"
405 "    - :class:`GetProjectedYF1D`\n"
406 "    - :class:`GetProjectedZF1D`\n"
407 "    - :class:`GetSteerableViewMapDensityF1D`\n"
408 "    - :class:`GetViewMapGradientNormF1D`\n"
409 "    - :class:`GetXF1D`\n"
410 "    - :class:`GetYF1D`\n"
411 "    - :class:`GetZF1D`\n"
412 "    - :class:`LocalAverageDepthF1D`\n"
413 "    - :class:`ZDiscontinuityF1D`\n"
414 "\n"
415 "  - :class:`UnaryFunction1DEdgeNature`\n"
416 "\n"
417 "    - :class:`CurveNatureF1D`\n"
418 "\n"
419 "  - :class:`UnaryFunction1DFloat`\n"
420 "  - :class:`UnaryFunction1DUnsigned`\n"
421 "\n"
422 "    - :class:`QuantitativeInvisibilityF1D`\n"
423 "\n"
424 "  - :class:`UnaryFunction1DVec2f`\n"
425 "\n"
426 "    - :class:`Normal2DF1D`\n"
427 "    - :class:`Orientation2DF1D`\n"
428 "\n"
429 "  - :class:`UnaryFunction1DVec3f`\n"
430 "\n"
431 "    - :class:`Orientation3DF1D`\n"
432 "\n"
433 "  - :class:`UnaryFunction1DVectorViewShape`\n"
434 "\n"
435 "    - :class:`GetOccludeeF1D`\n"
436 "    - :class:`GetOccludersF1D`\n"
437 "    - :class:`GetShapeF1D`\n"
438 "\n"
439 "  - :class:`UnaryFunction1DVoid`\n"
440 "\n"
441 "    - :class:`ChainingTimeStampF1D`\n"
442 "    - :class:`IncrementChainingTimeStampF1D`\n"
443 "    - :class:`TimeStampF1D`\n"
444 "\n"
445 "- :class:`UnaryPredicate0D`\n"
446 "\n"
447 "  - :class:`FalseUP0D`\n"
448 "  - :class:`TrueUP0D`\n"
449 "\n"
450 "- :class:`UnaryPredicate1D`\n"
451 "\n"
452 "  - :class:`ContourUP1D`\n"
453 "  - :class:`DensityLowerThanUP1D`\n"
454 "  - :class:`EqualToChainingTimeStampUP1D`\n"
455 "  - :class:`EqualToTimeStampUP1D`\n"
456 "  - :class:`ExternalContourUP1D`\n"
457 "  - :class:`FalseUP1D`\n"
458 "  - :class:`QuantitativeInvisibilityUP1D`\n"
459 "  - :class:`ShapeUP1D`\n"
460 "  - :class:`TrueUP1D`\n"
461 "  - :class:`WithinImageBoundaryUP1D`\n"
462 "\n"
463 "- :class:`ViewMap`\n"
464 "- :class:`ViewShape`\n"
465 "- :class:`IntegrationType`\n"
466 "- :class:`MediumType`\n"
467 "- :class:`Nature`\n"
468 "\n";
469
470 /*-----------------------Freestyle module method def---------------------------*/
471
472 static PyMethodDef module_functions[] = {
473         {"getCurrentScene", (PyCFunction) Freestyle_getCurrentScene, METH_NOARGS, Freestyle_getCurrentScene___doc__},
474         {"blendRamp", (PyCFunction) Freestyle_blendRamp, METH_VARARGS, Freestyle_blendRamp___doc__},
475         {"evaluateColorRamp", (PyCFunction) Freestyle_evaluateColorRamp, METH_VARARGS, Freestyle_evaluateColorRamp___doc__},
476         {"evaluateCurveMappingF", (PyCFunction) Freestyle_evaluateCurveMappingF, METH_VARARGS,
477                                   Freestyle_evaluateCurveMappingF___doc__},
478         {NULL, NULL, 0, NULL}
479 };
480
481 /*-----------------------Freestyle module definition---------------------------*/
482
483 static PyModuleDef module_definition = {
484     PyModuleDef_HEAD_INIT,
485     "freestyle",
486     module_docstring,
487     -1,
488     module_functions
489 };
490
491 //-------------------MODULE INITIALIZATION--------------------------------
492 PyObject *Freestyle_Init(void)
493 {
494         PyObject *module;
495         
496         // initialize modules
497         module = PyModule_Create(&module_definition);
498         if (!module)
499                 return NULL;
500         PyDict_SetItemString(PySys_GetObject("modules"), module_definition.m_name, module);
501         
502         // attach its classes (adding the object types to the module)
503         
504         // those classes have to be initialized before the others
505         MediumType_Init(module);
506         Nature_Init(module);
507
508         BBox_Init(module);
509         BinaryPredicate0D_Init(module);
510         BinaryPredicate1D_Init(module);
511         ContextFunctions_Init(module);
512         FrsMaterial_Init(module);
513         FrsNoise_Init(module);
514         Id_Init(module);
515         IntegrationType_Init(module);
516         Interface0D_Init(module);
517         Interface1D_Init(module);
518         Iterator_Init(module);
519         Operators_Init(module);
520         SShape_Init(module);
521         StrokeAttribute_Init(module);
522         StrokeShader_Init(module);
523         UnaryFunction0D_Init(module);
524         UnaryFunction1D_Init(module);
525         UnaryPredicate0D_Init(module);
526         UnaryPredicate1D_Init(module);
527         ViewMap_Init(module);
528         ViewShape_Init(module);
529
530         return module;
531 }
532
533 ///////////////////////////////////////////////////////////////////////////////////////////
534
535 #ifdef __cplusplus
536 }
537 #endif