2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * ***** END GPL LICENSE BLOCK *****
21 /** \file source/blender/freestyle/intern/python/BPy_Freestyle.cpp
25 #include "BPy_Freestyle.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"
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"
57 ///////////////////////////////////////////////////////////////////////////////////////////
59 //------------------------ MODULE FUNCTIONS ----------------------------------
61 #include "FRS_freestyle.h"
62 #include "RNA_access.h"
63 #include "BKE_appdir.h"
64 #include "DNA_scene_types.h"
65 #include "bpy_rna.h" /* pyrna_struct_CreatePyObject() */
67 static char Freestyle_getCurrentScene___doc__[] =
68 ".. function:: getCurrentScene()\n"
70 " Returns the current scene.\n"
72 " :return: The current scene.\n"
73 " :rtype: :class:`bpy.types.Scene`\n";
75 static PyObject *Freestyle_getCurrentScene(PyObject * /*self*/)
77 if (!freestyle_scene) {
78 PyErr_SetString(PyExc_TypeError, "current scene not available");
82 RNA_pointer_create(&freestyle_scene->id, &RNA_Scene, freestyle_scene, &ptr_scene);
83 return pyrna_struct_CreatePyObject(&ptr_scene);
86 #include "DNA_material_types.h"
88 static int ramp_blend_type(const char *type)
90 if (STREQ(type, "MIX")) return MA_RAMP_BLEND;
91 if (STREQ(type, "ADD")) return MA_RAMP_ADD;
92 if (STREQ(type, "MULTIPLY")) return MA_RAMP_MULT;
93 if (STREQ(type, "SUBTRACT")) return MA_RAMP_SUB;
94 if (STREQ(type, "SCREEN")) return MA_RAMP_SCREEN;
95 if (STREQ(type, "DIVIDE")) return MA_RAMP_DIV;
96 if (STREQ(type, "DIFFERENCE")) return MA_RAMP_DIFF;
97 if (STREQ(type, "DARKEN")) return MA_RAMP_DARK;
98 if (STREQ(type, "LIGHTEN")) return MA_RAMP_LIGHT;
99 if (STREQ(type, "OVERLAY")) return MA_RAMP_OVERLAY;
100 if (STREQ(type, "DODGE")) return MA_RAMP_DODGE;
101 if (STREQ(type, "BURN")) return MA_RAMP_BURN;
102 if (STREQ(type, "HUE")) return MA_RAMP_HUE;
103 if (STREQ(type, "SATURATION")) return MA_RAMP_SAT;
104 if (STREQ(type, "VALUE")) return MA_RAMP_VAL;
105 if (STREQ(type, "COLOR")) return MA_RAMP_COLOR;
106 if (STREQ(type, "SOFT_LIGHT")) return MA_RAMP_SOFT;
107 if (STREQ(type, "LINEAR_LIGHT")) return MA_RAMP_LINEAR;
111 #include "BKE_material.h" /* ramp_blend() */
113 static char Freestyle_blendRamp___doc__[] =
114 ".. function:: blendRamp(type, color1, fac, color2)\n"
116 " Blend two colors according to a ramp blend type.\n"
118 " :arg type: Ramp blend type.\n"
120 " :arg color1: 1st color.\n"
121 " :type color1: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
122 " :arg fac: Blend factor.\n"
123 " :type fac: float\n"
124 " :arg color2: 1st color.\n"
125 " :type color2: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
126 " :return: Blended color in RGB format.\n"
127 " :rtype: :class:`mathutils.Vector`\n";
129 static PyObject *Freestyle_blendRamp(PyObject * /*self*/, PyObject *args)
131 PyObject *obj1, *obj2;
134 float a[3], fac, b[3];
136 if (!PyArg_ParseTuple(args, "sOfO", &s, &obj1, &fac, &obj2))
138 type = ramp_blend_type(s);
140 PyErr_SetString(PyExc_TypeError, "argument 1 is an unknown ramp blend type");
143 if (mathutils_array_parse(a, 3, 3, obj1,
144 "argument 2 must be a 3D vector "
145 "(either a tuple/list of 3 elements or Vector)") == -1)
149 if (mathutils_array_parse(b, 3, 3, obj2,
150 "argument 4 must be a 3D vector "
151 "(either a tuple/list of 3 elements or Vector)") == -1)
155 ramp_blend(type, a, fac, b);
156 return Vector_CreatePyObject(a, 3, NULL);
159 #include "BKE_texture.h" /* do_colorband() */
161 static char Freestyle_evaluateColorRamp___doc__[] =
162 ".. function:: evaluateColorRamp(ramp, in)\n"
164 " Evaluate a color ramp at a point in the interval 0 to 1.\n"
166 " :arg ramp: Color ramp object.\n"
167 " :type ramp: :class:`bpy.types.ColorRamp`\n"
168 " :arg in: Value in the interval 0 to 1.\n"
170 " :return: color in RGBA format.\n"
171 " :rtype: :class:`mathutils.Vector`\n";
173 static PyObject *Freestyle_evaluateColorRamp(PyObject * /*self*/, PyObject *args)
175 BPy_StructRNA *py_srna;
179 if (!(PyArg_ParseTuple(args, "O!f", &pyrna_struct_Type, &py_srna, &in)))
181 if (!RNA_struct_is_a(py_srna->ptr.type, &RNA_ColorRamp)) {
182 PyErr_SetString(PyExc_TypeError, "1st argument is not a ColorRamp object");
185 coba = (ColorBand *)py_srna->ptr.data;
186 if (!do_colorband(coba, in, out)) {
187 PyErr_SetString(PyExc_ValueError, "failed to evaluate the color ramp");
190 return Vector_CreatePyObject(out, 4, NULL);
193 #include "DNA_color_types.h"
194 #include "BKE_colortools.h" /* curvemapping_evaluateF() */
196 static char Freestyle_evaluateCurveMappingF___doc__[] =
197 ".. function:: evaluateCurveMappingF(cumap, cur, value)\n"
199 " Evaluate a curve mapping at a point in the interval 0 to 1.\n"
201 " :arg cumap: Curve mapping object.\n"
202 " :type cumap: :class:`bpy.types.CurveMapping`\n"
203 " :arg cur: Index of the curve to be used (0 <= cur <= 3).\n"
205 " :arg value: Input value in the interval 0 to 1.\n"
206 " :type value: float\n"
207 " :return: Mapped output value.\n"
210 static PyObject *Freestyle_evaluateCurveMappingF(PyObject * /*self*/, PyObject *args)
212 BPy_StructRNA *py_srna;
217 if (!(PyArg_ParseTuple(args, "O!if", &pyrna_struct_Type, &py_srna, &cur, &value)))
219 if (!RNA_struct_is_a(py_srna->ptr.type, &RNA_CurveMapping)) {
220 PyErr_SetString(PyExc_TypeError, "1st argument is not a CurveMapping object");
223 if (cur < 0 || cur > 3) {
224 PyErr_SetString(PyExc_ValueError, "2nd argument is out of range");
227 cumap = (CurveMapping *)py_srna->ptr.data;
228 curvemapping_initialize(cumap);
229 /* disable extrapolation if enabled */
230 if ((cumap->cm[cur].flag & CUMA_EXTEND_EXTRAPOLATE)) {
231 cumap->cm[cur].flag &= ~(CUMA_EXTEND_EXTRAPOLATE);
232 curvemapping_changed(cumap, 0);
234 return PyFloat_FromDouble(curvemapping_evaluateF(cumap, cur, value));
237 /*-----------------------Freestyle module docstring----------------------------*/
239 static char module_docstring[] =
240 "This module provides classes for defining line drawing rules (such as\n"
241 "predicates, functions, chaining iterators, and stroke shaders), as well\n"
242 "as helper functions for style module writing.\n"
247 "- :class:`BinaryPredicate0D`\n"
248 "- :class:`BinaryPredicate1D`\n"
250 " - :class:`FalseBP1D`\n"
251 " - :class:`Length2DBP1D`\n"
252 " - :class:`SameShapeIdBP1D`\n"
253 " - :class:`TrueBP1D`\n"
254 " - :class:`ViewMapGradientNormBP1D`\n"
257 "- :class:`Interface0D`\n"
259 " - :class:`CurvePoint`\n"
261 " - :class:`StrokeVertex`\n"
263 " - :class:`SVertex`\n"
264 " - :class:`ViewVertex`\n"
266 " - :class:`NonTVertex`\n"
267 " - :class:`TVertex`\n"
269 "- :class:`Interface1D`\n"
271 " - :class:`Curve`\n"
273 " - :class:`Chain`\n"
275 " - :class:`FEdge`\n"
277 " - :class:`FEdgeSharp`\n"
278 " - :class:`FEdgeSmooth`\n"
280 " - :class:`Stroke`\n"
281 " - :class:`ViewEdge`\n"
283 "- :class:`Iterator`\n"
285 " - :class:`AdjacencyIterator`\n"
286 " - :class:`CurvePointIterator`\n"
287 " - :class:`Interface0DIterator`\n"
288 " - :class:`SVertexIterator`\n"
289 " - :class:`StrokeVertexIterator`\n"
290 " - :class:`ViewEdgeIterator`\n"
292 " - :class:`ChainingIterator`\n"
294 " - :class:`ChainPredicateIterator`\n"
295 " - :class:`ChainSilhouetteIterator`\n"
297 " - :class:`orientedViewEdgeIterator`\n"
299 "- :class:`Material`\n"
301 "- :class:`Operators`\n"
302 "- :class:`SShape`\n"
303 "- :class:`StrokeAttribute`\n"
304 "- :class:`StrokeShader`\n"
306 " - :class:`BackboneStretcherShader`\n"
307 " - :class:`BezierCurveShader`\n"
308 " - :class:`BlenderTextureShader`\n"
309 " - :class:`CalligraphicShader`\n"
310 " - :class:`ColorNoiseShader`\n"
311 " - :class:`ColorVariationPatternShader`\n"
312 " - :class:`ConstantColorShader`\n"
313 " - :class:`ConstantThicknessShader`\n"
314 " - :class:`ConstrainedIncreasingThicknessShader`\n"
315 " - :class:`GuidingLinesShader`\n"
316 " - :class:`IncreasingColorShader`\n"
317 " - :class:`IncreasingThicknessShader`\n"
318 " - :class:`PolygonalizationShader`\n"
319 " - :class:`SamplingShader`\n"
320 " - :class:`SmoothingShader`\n"
321 " - :class:`SpatialNoiseShader`\n"
322 " - :class:`StrokeTextureShader`\n"
323 " - :class:`StrokeTextureStepShader`\n"
324 " - :class:`TextureAssignerShader`\n"
325 " - :class:`ThicknessNoiseShader`\n"
326 " - :class:`ThicknessVariationPatternShader`\n"
327 " - :class:`TipRemoverShader`\n"
328 " - :class:`fstreamShader`\n"
329 " - :class:`streamShader`\n"
331 "- :class:`UnaryFunction0D`\n"
333 " - :class:`UnaryFunction0DDouble`\n"
335 " - :class:`Curvature2DAngleF0D`\n"
336 " - :class:`DensityF0D`\n"
337 " - :class:`GetProjectedXF0D`\n"
338 " - :class:`GetProjectedYF0D`\n"
339 " - :class:`GetProjectedZF0D`\n"
340 " - :class:`GetXF0D`\n"
341 " - :class:`GetYF0D`\n"
342 " - :class:`GetZF0D`\n"
343 " - :class:`LocalAverageDepthF0D`\n"
344 " - :class:`ZDiscontinuityF0D`\n"
346 " - :class:`UnaryFunction0DEdgeNature`\n"
348 " - :class:`CurveNatureF0D`\n"
350 " - :class:`UnaryFunction0DFloat`\n"
352 " - :class:`GetCurvilinearAbscissaF0D`\n"
353 " - :class:`GetParameterF0D`\n"
354 " - :class:`GetViewMapGradientNormF0D`\n"
355 " - :class:`ReadCompleteViewMapPixelF0D`\n"
356 " - :class:`ReadMapPixelF0D`\n"
357 " - :class:`ReadSteerableViewMapPixelF0D`\n"
359 " - :class:`UnaryFunction0DId`\n"
361 " - :class:`ShapeIdF0D`\n"
363 " - :class:`UnaryFunction0DMaterial`\n"
365 " - :class:`MaterialF0D`\n"
367 " - :class:`UnaryFunction0DUnsigned`\n"
369 " - :class:`QuantitativeInvisibilityF0D`\n"
371 " - :class:`UnaryFunction0DVec2f`\n"
373 " - :class:`Normal2DF0D`\n"
374 " - :class:`VertexOrientation2DF0D`\n"
376 " - :class:`UnaryFunction0DVec3f`\n"
378 " - :class:`VertexOrientation3DF0D`\n"
380 " - :class:`UnaryFunction0DVectorViewShape`\n"
382 " - :class:`GetOccludersF0D`\n"
384 " - :class:`UnaryFunction0DViewShape`\n"
386 " - :class:`GetOccludeeF0D`\n"
387 " - :class:`GetShapeF0D`\n"
389 "- :class:`UnaryFunction1D`\n"
391 " - :class:`UnaryFunction1DDouble`\n"
393 " - :class:`Curvature2DAngleF1D`\n"
394 " - :class:`DensityF1D`\n"
395 " - :class:`GetCompleteViewMapDensityF1D`\n"
396 " - :class:`GetDirectionalViewMapDensityF1D`\n"
397 " - :class:`GetProjectedXF1D`\n"
398 " - :class:`GetProjectedYF1D`\n"
399 " - :class:`GetProjectedZF1D`\n"
400 " - :class:`GetSteerableViewMapDensityF1D`\n"
401 " - :class:`GetViewMapGradientNormF1D`\n"
402 " - :class:`GetXF1D`\n"
403 " - :class:`GetYF1D`\n"
404 " - :class:`GetZF1D`\n"
405 " - :class:`LocalAverageDepthF1D`\n"
406 " - :class:`ZDiscontinuityF1D`\n"
408 " - :class:`UnaryFunction1DEdgeNature`\n"
410 " - :class:`CurveNatureF1D`\n"
412 " - :class:`UnaryFunction1DFloat`\n"
413 " - :class:`UnaryFunction1DUnsigned`\n"
415 " - :class:`QuantitativeInvisibilityF1D`\n"
417 " - :class:`UnaryFunction1DVec2f`\n"
419 " - :class:`Normal2DF1D`\n"
420 " - :class:`Orientation2DF1D`\n"
422 " - :class:`UnaryFunction1DVec3f`\n"
424 " - :class:`Orientation3DF1D`\n"
426 " - :class:`UnaryFunction1DVectorViewShape`\n"
428 " - :class:`GetOccludeeF1D`\n"
429 " - :class:`GetOccludersF1D`\n"
430 " - :class:`GetShapeF1D`\n"
432 " - :class:`UnaryFunction1DVoid`\n"
434 " - :class:`ChainingTimeStampF1D`\n"
435 " - :class:`IncrementChainingTimeStampF1D`\n"
436 " - :class:`TimeStampF1D`\n"
438 "- :class:`UnaryPredicate0D`\n"
440 " - :class:`FalseUP0D`\n"
441 " - :class:`TrueUP0D`\n"
443 "- :class:`UnaryPredicate1D`\n"
445 " - :class:`ContourUP1D`\n"
446 " - :class:`DensityLowerThanUP1D`\n"
447 " - :class:`EqualToChainingTimeStampUP1D`\n"
448 " - :class:`EqualToTimeStampUP1D`\n"
449 " - :class:`ExternalContourUP1D`\n"
450 " - :class:`FalseUP1D`\n"
451 " - :class:`QuantitativeInvisibilityUP1D`\n"
452 " - :class:`ShapeUP1D`\n"
453 " - :class:`TrueUP1D`\n"
454 " - :class:`WithinImageBoundaryUP1D`\n"
456 "- :class:`ViewMap`\n"
457 "- :class:`ViewShape`\n"
458 "- :class:`IntegrationType`\n"
459 "- :class:`MediumType`\n"
460 "- :class:`Nature`\n"
463 /*-----------------------Freestyle module method def---------------------------*/
465 static PyMethodDef module_functions[] = {
466 {"getCurrentScene", (PyCFunction) Freestyle_getCurrentScene, METH_NOARGS, Freestyle_getCurrentScene___doc__},
467 {"blendRamp", (PyCFunction) Freestyle_blendRamp, METH_VARARGS, Freestyle_blendRamp___doc__},
468 {"evaluateColorRamp", (PyCFunction) Freestyle_evaluateColorRamp, METH_VARARGS, Freestyle_evaluateColorRamp___doc__},
469 {"evaluateCurveMappingF", (PyCFunction) Freestyle_evaluateCurveMappingF, METH_VARARGS,
470 Freestyle_evaluateCurveMappingF___doc__},
471 {NULL, NULL, 0, NULL}
474 /*-----------------------Freestyle module definition---------------------------*/
476 static PyModuleDef module_definition = {
477 PyModuleDef_HEAD_INIT,
484 //-------------------MODULE INITIALIZATION--------------------------------
485 PyObject *Freestyle_Init(void)
489 // initialize modules
490 module = PyModule_Create(&module_definition);
493 PyDict_SetItemString(PySys_GetObject("modules"), module_definition.m_name, module);
495 // update 'sys.path' for Freestyle Python API modules
496 const char * const path = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, "freestyle");
498 char modpath[FILE_MAX];
499 BLI_join_dirfile(modpath, sizeof(modpath), path, "modules");
500 PyObject *sys_path = PySys_GetObject("path"); /* borrow */
501 PyObject *py_modpath = PyUnicode_FromString(modpath);
502 PyList_Append(sys_path, py_modpath);
503 Py_DECREF(py_modpath);
505 printf("Adding Python path: %s\n", modpath);
509 printf("Freestyle: couldn't find 'scripts/freestyle/modules', Freestyle won't work properly.\n");
512 // attach its classes (adding the object types to the module)
514 // those classes have to be initialized before the others
515 MediumType_Init(module);
519 BinaryPredicate0D_Init(module);
520 BinaryPredicate1D_Init(module);
521 ContextFunctions_Init(module);
522 FrsMaterial_Init(module);
523 FrsNoise_Init(module);
525 IntegrationType_Init(module);
526 Interface0D_Init(module);
527 Interface1D_Init(module);
528 Iterator_Init(module);
529 Operators_Init(module);
531 StrokeAttribute_Init(module);
532 StrokeShader_Init(module);
533 UnaryFunction0D_Init(module);
534 UnaryFunction1D_Init(module);
535 UnaryPredicate0D_Init(module);
536 UnaryPredicate1D_Init(module);
537 ViewMap_Init(module);
538 ViewShape_Init(module);
543 ///////////////////////////////////////////////////////////////////////////////////////////