diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2010-07-28 04:43:45 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2010-07-28 04:43:45 +0400 |
commit | a99a466feec7c2e88af967769205f43fa74f1161 (patch) | |
tree | afb78af7143c2f0cd7d1d2c431d15550de4a9b94 | |
parent | be2e221608971d6e6618887ce40998c993c68ac8 (diff) |
* Made the Parameter Editor mode much more functional. Edge selection
criteria, as well as the color/alpha/thickness Along Stroke modifiers
now work.
* Added more curve blend types. The default is set to "MIX".
-rw-r--r-- | release/scripts/freestyle/style_modules/parameter_editor.py | 237 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/linestyle.c | 12 | ||||
-rw-r--r-- | source/blender/freestyle/intern/python/BPy_Freestyle.cpp | 88 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_linestyle_types.h | 8 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_linestyle.c | 6 |
5 files changed, 332 insertions, 19 deletions
diff --git a/release/scripts/freestyle/style_modules/parameter_editor.py b/release/scripts/freestyle/style_modules/parameter_editor.py index e423a0f349a..5fde8eda184 100644 --- a/release/scripts/freestyle/style_modules/parameter_editor.py +++ b/release/scripts/freestyle/style_modules/parameter_editor.py @@ -23,20 +23,245 @@ from logical_operators import * from ChainingIterators import * from shaders import * +def blend_curve(blend_type, v1, fac, v2): + facm = 1.0 - fac + if blend_type == "MIX": + v1 = facm * v1 + fac * v2 + elif blend_type == "ADD": + v1 += fac * v2 + elif blend_type == "MULTIPLY": + v1 *= facm + fac * v2; + elif blend_type == "SUBTRACT": + v1 -= fac * v2 + elif blend_type == "DIVIDE": + if v2 != 0.0: + v1 = facm * v1 + fac * v1 / v2 + elif blend_type == "DIFFERENCE": + v1 = facm * v1 + fac * abs(v1 - v2) + elif blend_type == "MININUM": + tmp = fac * v1 + if v1 > tmp: + v1 = tmp + elif blend_type == "MAXIMUM": + tmp = fac * v1 + if v1 < tmp: + v1 = tmp + else: + raise ValueError("unknown curve blend type: " + blend_type) + return v1 + +class ColorAlongStrokeShader(StrokeShader): + def __init__(self, blend, influence, ramp): + StrokeShader.__init__(self) + self.__blend = blend + self.__influence = influence + self.__ramp = ramp + def getName(self): + return "ColorAlongStrokeShader" + def shade(self, stroke): + distance, total = 0.0, stroke.getLength2D() + it = stroke.strokeVerticesBegin() + while not it.isEnd(): + sv = it.getObject() + p = sv.getPoint() + if not it.isBegin(): + distance += (prev - p).length + prev = p + t = min(distance / total, 1.0) + b = Freestyle.evaluateColorRamp(self.__ramp, t) + b = b.xyz # omit alpha + a = sv.attribute().getColorRGB() + c = Freestyle.blendRamp(self.__blend, a, self.__influence, b) + sv.attribute().setColor(c) + it.increment() + +class AlphaAlongStrokeShader(StrokeShader): + def __init__(self, blend, influence, mapping, invert, curve): + StrokeShader.__init__(self) + self.__blend = blend + self.__influence = influence + assert mapping in ("LINEAR", "CURVE") + self.__mapping = getattr(self, mapping) + self.__invert = invert + self.__curve = curve + def getName(self): + return "AlphaAlongStrokeShader" + def LINEAR(self, t): + if self.__invert: + return 1.0 - t + return t + def CURVE(self, t): + return Freestyle.evaluateCurveMappingF(self.__curve, 0, t) + def shade(self, stroke): + distance, total = 0.0, stroke.getLength2D() + it = stroke.strokeVerticesBegin() + while not it.isEnd(): + sv = it.getObject() + p = sv.getPoint() + if not it.isBegin(): + distance += (prev - p).length + prev = p + t = min(distance / total, 1.0) + b = self.__mapping(t) + a = sv.attribute().getAlpha() + c = blend_curve(self.__blend, a, self.__influence, b) + sv.attribute().setAlpha(c) + it.increment() + +class ThicknessAlongStrokeShader(StrokeShader): + def __init__(self, blend, influence, mapping, invert, curve, value_min, value_max): + StrokeShader.__init__(self) + self.__blend = blend + self.__influence = influence + assert mapping in ("LINEAR", "CURVE") + self.__mapping = getattr(self, mapping) + self.__invert = invert + self.__curve = curve + self.__value_min = value_min + self.__value_max = value_max + def getName(self): + return "ThicknessAlongStrokeShader" + def LINEAR(self, t): + if self.__invert: + return 1.0 - t + return t + def CURVE(self, t): + return Freestyle.evaluateCurveMappingF(self.__curve, 0, t) + def shade(self, stroke): + distance, total = 0.0, stroke.getLength2D() + it = stroke.strokeVerticesBegin() + while not it.isEnd(): + sv = it.getObject() + p = sv.getPoint() + if not it.isBegin(): + distance += (prev - p).length + prev = p + t = min(distance / total, 1.0) + t = self.__mapping(t) + b = self.__value_min + t * (self.__value_max - self.__value_min) + a = sv.attribute().getThicknessRL() + a = a[0] + a[1] + c = blend_curve(self.__blend, a, self.__influence, b) + sv.attribute().setThickness(c/2, c/2) + it.increment() + +class QuantitativeInvisibilityRangeUP1D(UnaryPredicate1D): + def __init__(self, qi_start, qi_end): + UnaryPredicate1D.__init__(self) + self.__getQI = QuantitativeInvisibilityF1D() + self.__qi_start = qi_start + self.__qi_end = qi_end + def getName(self): + return "QuantitativeInvisibilityRangeUP1D" + def __call__(self, inter): + qi = self.__getQI(inter) + return self.__qi_start <= qi <= self.__qi_end + +def join_unary_predicates(upred_list, bpred): + if not upred_list: + return TrueUP1D() + upred = upred_list[0] + for p in upred_list[1:]: + upred = bpred(upred, p) + return upred + def process(layer_name, lineset_name): scene = Freestyle.getCurrentScene() layer = scene.render.layers[layer_name] lineset = layer.freestyle_settings.linesets[lineset_name] linestyle = lineset.linestyle - color = linestyle.color - - upred = QuantitativeInvisibilityUP1D(0) + selection_criteria = [] + # prepare selection criteria by visibility + if lineset.select_by_visibility: + if lineset.visibility == "VISIBLE": + selection_criteria.append( + QuantitativeInvisibilityUP1D(0)) + elif lineset.visibility == "HIDDEN": + selection_criteria.append( + NotUP1D(QuantitativeInvisibilityUP1D(0))) + elif lineset.visibility == "RANGE": + selection_criteria.append( + QuantitativeInvisibilityRangeUP1D(lineset.qi_start, lineset.qi_end)) + # prepare selection criteria by edge types + if lineset.select_by_edge_types: + edge_type_criteria = [] + if lineset.edge_type_combination == "OR": + flags = Nature.NO_FEATURE + if lineset.select_silhouette: + flags |= Nature.SILHOUETTE + if lineset.select_border: + flags |= Nature.BORDER + if lineset.select_crease: + flags |= Nature.CREASE + if lineset.select_ridge: + flags |= Nature.RIDGE + if lineset.select_valley: + flags |= Nature.VALLEY + if lineset.select_suggestive_contour: + flags |= Nature.SUGGESTIVE_CONTOUR + if lineset.select_material_boundary: + flags |= Nature.MATERIAL_BOUNDARY + if flags != Nature.NO_FEATURE: + edge_type_criteria.append(pyNatureUP1D(flags)) + else: + if lineset.select_silhouette: + edge_type_criteria.append(pyNatureUP1D(Nature.SILHOUETTE)) + if lineset.select_border: + edge_type_criteria.append(pyNatureUP1D(Nature.BORDER)) + if lineset.select_crease: + edge_type_criteria.append(pyNatureUP1D(Nature.CREASE)) + if lineset.select_ridge: + edge_type_criteria.append(pyNatureUP1D(Nature.RIDGE)) + if lineset.select_valley: + edge_type_criteria.append(pyNatureUP1D(Nature.VALLEY)) + if lineset.select_suggestive_contour: + edge_type_criteria.append(pyNatureUP1D(Nature.SUGGESTIVE_CONTOUR)) + if lineset.select_material_boundary: + edge_type_criteria.append(pyNatureUP1D(Nature.MATERIAL_BOUNDARY)) + if lineset.select_contour: + edge_type_criteria.append(ContourUP1D()) + if lineset.select_external_contour: + edge_type_criteria.append(ExternalContourUP1D()) + if lineset.edge_type_combination == "OR": + upred = join_unary_predicates(edge_type_criteria, OrUP1D) + else: + upred = join_unary_predicates(edge_type_criteria, AndUP1D) + if upred is not None: + if lineset.edge_type_negation == "EXCLUSIVE": + upred = NotUP1D(upred) + selection_criteria.append(upred) + # do feature edge selection + upred = join_unary_predicates(selection_criteria, AndUP1D) + if upred is None: + upred = TrueUP1D() Operators.select(upred) - Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) + # join feature edges + Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) # FIXME + # prepare a list of stroke shaders + color = linestyle.color shaders_list = [ SamplingShader(5.0), ConstantThicknessShader(linestyle.thickness), - ConstantColorShader(color.r, color.g, color.b, linestyle.alpha) - ] + ConstantColorShader(color.r, color.g, color.b, linestyle.alpha)] + for m in linestyle.color_modifiers: + if not m.enabled: + continue + if m.type == "ALONG_STROKE": + shaders_list.append( + ColorAlongStrokeShader(m.blend, m.influence, m.color_ramp)) + for m in linestyle.alpha_modifiers: + if not m.enabled: + continue + if m.type == "ALONG_STROKE": + shaders_list.append( + AlphaAlongStrokeShader(m.blend, m.influence, m.mapping, m.invert, m.curve)) + for m in linestyle.thickness_modifiers: + if not m.enabled: + continue + if m.type == "ALONG_STROKE": + shaders_list.append( + ThicknessAlongStrokeShader(m.blend, m.influence, m.mapping, m.invert, m.curve, + m.value_min, m.value_max)) + # create strokes using the shaders list Operators.create(TrueUP1D(), shaders_list) diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index e97b4a5be92..acd8f0e4368 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -183,18 +183,18 @@ int FRS_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, int type) switch (type) { case LS_MODIFIER_ALONG_STROKE: ((LineStyleAlphaModifier_AlongStroke *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); - ((LineStyleAlphaModifier_AlongStroke *)m)->blend = LS_VALUE_ADD; + ((LineStyleAlphaModifier_AlongStroke *)m)->blend = LS_VALUE_BLEND; break; case LS_MODIFIER_DISTANCE_FROM_CAMERA: ((LineStyleAlphaModifier_DistanceFromCamera *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); - ((LineStyleAlphaModifier_DistanceFromCamera *)m)->blend = LS_VALUE_ADD; + ((LineStyleAlphaModifier_DistanceFromCamera *)m)->blend = LS_VALUE_BLEND; ((LineStyleAlphaModifier_DistanceFromCamera *)m)->range_min = 0.0f; ((LineStyleAlphaModifier_DistanceFromCamera *)m)->range_max = 10000.0f; break; case LS_MODIFIER_DISTANCE_FROM_OBJECT: ((LineStyleAlphaModifier_DistanceFromObject *)m)->target = NULL; ((LineStyleAlphaModifier_DistanceFromObject *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); - ((LineStyleAlphaModifier_DistanceFromObject *)m)->blend = LS_VALUE_ADD; + ((LineStyleAlphaModifier_DistanceFromObject *)m)->blend = LS_VALUE_BLEND; ((LineStyleAlphaModifier_DistanceFromObject *)m)->range_min = 0.0f; ((LineStyleAlphaModifier_DistanceFromObject *)m)->range_max = 10000.0f; break; @@ -240,13 +240,13 @@ int FRS_add_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, int type switch (type) { case LS_MODIFIER_ALONG_STROKE: ((LineStyleThicknessModifier_AlongStroke *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); - ((LineStyleThicknessModifier_AlongStroke *)m)->blend = LS_VALUE_ADD; + ((LineStyleThicknessModifier_AlongStroke *)m)->blend = LS_VALUE_BLEND; ((LineStyleThicknessModifier_AlongStroke *)m)->value_min = 0.0f; ((LineStyleThicknessModifier_AlongStroke *)m)->value_max = 1.0f; break; case LS_MODIFIER_DISTANCE_FROM_CAMERA: ((LineStyleThicknessModifier_DistanceFromCamera *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); - ((LineStyleThicknessModifier_DistanceFromCamera *)m)->blend = LS_VALUE_ADD; + ((LineStyleThicknessModifier_DistanceFromCamera *)m)->blend = LS_VALUE_BLEND; ((LineStyleThicknessModifier_DistanceFromCamera *)m)->range_min = 0.0f; ((LineStyleThicknessModifier_DistanceFromCamera *)m)->range_max = 1000.0f; ((LineStyleThicknessModifier_DistanceFromCamera *)m)->value_min = 0.0f; @@ -255,7 +255,7 @@ int FRS_add_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, int type case LS_MODIFIER_DISTANCE_FROM_OBJECT: ((LineStyleThicknessModifier_DistanceFromObject *)m)->target = NULL; ((LineStyleThicknessModifier_DistanceFromObject *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); - ((LineStyleThicknessModifier_DistanceFromObject *)m)->blend = LS_VALUE_ADD; + ((LineStyleThicknessModifier_DistanceFromObject *)m)->blend = LS_VALUE_BLEND; ((LineStyleThicknessModifier_DistanceFromObject *)m)->range_min = 0.0f; ((LineStyleThicknessModifier_DistanceFromObject *)m)->range_max = 1000.0f; ((LineStyleThicknessModifier_DistanceFromObject *)m)->value_min = 0.0f; diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp index 1e6c063a681..1f29c8d24c1 100644 --- a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp +++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp @@ -4,6 +4,7 @@ #include "BPy_BinaryPredicate0D.h" #include "BPy_BinaryPredicate1D.h" #include "BPy_ContextFunctions.h" +#include "BPy_Convert.h" #include "BPy_FrsMaterial.h" #include "BPy_FrsNoise.h" #include "BPy_Id.h" @@ -55,6 +56,88 @@ static PyObject *Freestyle_getCurrentScene( PyObject *self ) return pyrna_struct_CreatePyObject(&ptr_scene); } +#include "DNA_material_types.h" + +static int ramp_blend_type(const char *type) +{ + if (!strcmp(type, "MIX")) return MA_RAMP_BLEND; + if (!strcmp(type, "ADD")) return MA_RAMP_ADD; + if (!strcmp(type, "MULTIPLY")) return MA_RAMP_MULT; + if (!strcmp(type, "SUBTRACT")) return MA_RAMP_SUB; + if (!strcmp(type, "SCREEN")) return MA_RAMP_SCREEN; + if (!strcmp(type, "DIVIDE")) return MA_RAMP_DIV; + if (!strcmp(type, "DIFFERENCE")) return MA_RAMP_DIFF; + if (!strcmp(type, "DARKEN")) return MA_RAMP_DARK; + if (!strcmp(type, "LIGHTEN")) return MA_RAMP_LIGHT; + if (!strcmp(type, "OVERLAY")) return MA_RAMP_OVERLAY; + if (!strcmp(type, "DODGE")) return MA_RAMP_DODGE; + if (!strcmp(type, "BURN")) return MA_RAMP_BURN; + if (!strcmp(type, "HUE")) return MA_RAMP_HUE; + if (!strcmp(type, "SATURATION")) return MA_RAMP_SAT; + if (!strcmp(type, "VALUE")) return MA_RAMP_VAL; + if (!strcmp(type, "COLOR")) return MA_RAMP_COLOR; + if (!strcmp(type, "SOFT LIGHT")) return MA_RAMP_SOFT; + if (!strcmp(type, "LINEAR LIGHT")) return MA_RAMP_LINEAR; + return -1; +} + +#include "BKE_material.h" /* ramp_blend() */ + +static char Freestyle_blendRamp___doc__[] = +".. function:: blendRamp(type, color1, fac, color2)\n" +"\n" +" Blend two colors according to a ramp blend type.\n" +"\n" +" :arg type: Ramp blend type.\n" +" :type type: int\n" +" :arg color1: 1st color.\n" +" :type color1: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n" +" :arg fac: Blend factor.\n" +" :type fac: float\n" +" :arg color2: 1st color.\n" +" :type color2: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n" +" :return: Blended color in RGB format.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static PyObject *Freestyle_blendRamp( PyObject *self, PyObject *args ) +{ + PyObject *obj1, *obj2; + char *s; + int type; + Vec3f *v1 = NULL, *v2 = NULL; + float a[3], fac, b[3]; + + if (!PyArg_ParseTuple(args, "sOfO", &s, &obj1, &fac, &obj2)) + return NULL; + type = ramp_blend_type(s); + if (type < 0) { + PyErr_SetString(PyExc_TypeError, "argument 1 is an unknown ramp blend type"); + goto error; + } + v1 = Vec3f_ptr_from_PyObject(obj1); + if (!v1) { + PyErr_SetString(PyExc_TypeError, "argument 2 must be a 3D vector (either a tuple/list of 3 elements or Vector)"); + goto error; + } + v2 = Vec3f_ptr_from_PyObject(obj2); + if (!v2) { + PyErr_SetString(PyExc_TypeError, "argument 4 must be a 3D vector (either a tuple/list of 3 elements or Vector)"); + goto error; + } + a[0] = v1->x(); b[0] = v2->x(); + a[1] = v1->y(); b[1] = v2->y(); + a[2] = v1->z(); b[2] = v2->z(); + ramp_blend(type, &a[0], &a[1], &a[2], fac, b); + delete v1; + delete v2; + return newVectorObject( a, 3, Py_NEW, NULL); + +error: + if (v1) delete v1; + if (v2) delete v2; + return NULL; +} + #include "BKE_texture.h" /* do_colorband() */ static char Freestyle_evaluateColorRamp___doc__[] = @@ -67,7 +150,7 @@ static char Freestyle_evaluateColorRamp___doc__[] = " :arg in: Value in the interval 0 to 1.\n" " :type in: float\n" " :return: color in RGBA format.\n" -" :rtype: Tuple of 4 float values\n"; +" :rtype: :class:`mathutils.Vector`\n"; static PyObject *Freestyle_evaluateColorRamp( PyObject *self, PyObject *args ) { @@ -86,7 +169,7 @@ static PyObject *Freestyle_evaluateColorRamp( PyObject *self, PyObject *args ) PyErr_SetString(PyExc_ValueError, "failed to evaluate the color ramp"); return NULL; } - return Py_BuildValue("(f,f,f,f)", out[0], out[1], out[2], out[3]); + return newVectorObject( out, 4, Py_NEW, NULL); } #include "BKE_colortools.h" /* curvemapping_evaluateF() */ @@ -134,6 +217,7 @@ static char module_docstring[] = "The Blender Freestyle module\n\n"; static PyMethodDef module_functions[] = { {"getCurrentScene", ( PyCFunction ) Freestyle_getCurrentScene, METH_NOARGS, Freestyle_getCurrentScene___doc__}, + {"blendRamp", ( PyCFunction ) Freestyle_blendRamp, METH_VARARGS, Freestyle_blendRamp___doc__}, {"evaluateColorRamp", ( PyCFunction ) Freestyle_evaluateColorRamp, METH_VARARGS, Freestyle_evaluateColorRamp___doc__}, {"evaluateCurveMappingF", ( PyCFunction ) Freestyle_evaluateCurveMappingF, METH_VARARGS, Freestyle_evaluateCurveMappingF___doc__}, {NULL, NULL, 0, NULL} diff --git a/source/blender/makesdna/DNA_linestyle_types.h b/source/blender/makesdna/DNA_linestyle_types.h index 2d6f4951875..6f55b3459b4 100644 --- a/source/blender/makesdna/DNA_linestyle_types.h +++ b/source/blender/makesdna/DNA_linestyle_types.h @@ -62,12 +62,14 @@ typedef struct LineStyleModifier { #define LS_MODIFIER_INVERT 2 /* blend (for alpha & thickness) */ +#define LS_VALUE_BLEND 0 #define LS_VALUE_ADD 1 -#define LS_VALUE_MUL 2 +#define LS_VALUE_MULT 2 #define LS_VALUE_SUB 3 #define LS_VALUE_DIV 4 -#define LS_VALUE_MIN 5 -#define LS_VALUE_MAX 6 +#define LS_VALUE_DIFF 5 +#define LS_VALUE_MIN 6 +#define LS_VALUE_MAX 7 /* Along Stroke modifiers */ diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c index 622f14a8af1..de7fe1a8258 100644 --- a/source/blender/makesrna/intern/rna_linestyle.c +++ b/source/blender/makesrna/intern/rna_linestyle.c @@ -213,10 +213,12 @@ static void rna_def_modifier_curve_common(StructRNA *srna, int range, int value) {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem value_blend_items[] = { - {LS_VALUE_ADD, "ADD", 0, "Addd", ""}, - {LS_VALUE_MUL, "MULTIPLY", 0, "Multiply", ""}, + {LS_VALUE_BLEND, "MIX", 0, "Mix", ""}, + {LS_VALUE_ADD, "ADD", 0, "Add", ""}, {LS_VALUE_SUB, "SUBTRACT", 0, "Subtract", ""}, + {LS_VALUE_MULT, "MULTIPLY", 0, "Multiply", ""}, {LS_VALUE_DIV, "DIVIDE", 0, "Divide", ""}, + {LS_VALUE_DIFF, "DIFFERENCE", 0, "Divide", ""}, {LS_VALUE_MIN, "MININUM", 0, "Minimum", ""}, {LS_VALUE_MAX, "MAXIMUM", 0, "Maximum", ""}, {0, NULL, 0, NULL, NULL}}; |