diff options
-rw-r--r-- | release/scripts/freestyle/style_modules/parameter_editor.py | 105 | ||||
-rw-r--r-- | release/scripts/ui/properties_render.py | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/linestyle.c | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_linestyle_types.h | 11 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_linestyle.c | 16 |
5 files changed, 135 insertions, 5 deletions
diff --git a/release/scripts/freestyle/style_modules/parameter_editor.py b/release/scripts/freestyle/style_modules/parameter_editor.py index 8b43fd0e9f1..fe53c2e5152 100644 --- a/release/scripts/freestyle/style_modules/parameter_editor.py +++ b/release/scripts/freestyle/style_modules/parameter_editor.py @@ -17,6 +17,7 @@ # ##### END GPL LICENSE BLOCK ##### import Freestyle +import math from freestyle_init import * from logical_operators import * @@ -298,6 +299,99 @@ def join_unary_predicates(upred_list, bpred): upred = bpred(upred, p) return upred +# Stroke caps + +def iter_stroke_vertices(stroke): + it = stroke.strokeVerticesBegin() + while not it.isEnd(): + yield it.getObject() + it.increment() + +class RoundCapShader(StrokeShader): + def round_cap_thickness(self, x): + x = max(0.0, min(x, 1.0)) + return math.sqrt(1.0 - (x ** 2)) + def shade(self, stroke): + # save the location and attribute of stroke vertices + buffer = [] + for sv in iter_stroke_vertices(stroke): + buffer.append((sv.getPoint(), sv.attribute())) + # calculate the number of additional vertices to form caps + R, L = stroke[0].attribute().getThicknessRL() + caplen_beg = (R + L) / 2.0 + nverts_beg = max(5, int(R + L)) + R, L = stroke[-1].attribute().getThicknessRL() + caplen_end = (R + L) / 2.0 + nverts_end = max(5, int(R + L)) + # increase the total number of stroke vertices + nverts = stroke.strokeVerticesSize() + stroke.Resample(nverts + nverts_beg + nverts_end) + # restore the location and attribute of the original vertices + for i in range(nverts): + p, attr = buffer[i] + stroke[nverts_beg + i].setPoint(p) + stroke[nverts_beg + i].setAttribute(attr) + # reshape the cap at the beginning of the stroke + q, attr = buffer[1] + p, attr = buffer[0] + d = p - q + d = d / d.length * caplen_beg + n = 1.0 / nverts_beg + R, L = attr.getThicknessRL() + for i in range(nverts_beg): + t = (nverts_beg - i) * n + stroke[i].setPoint(p + d * t) + r = self.round_cap_thickness((nverts_beg - i + 1) * n) + stroke[i].setAttribute(attr) + stroke[i].attribute().setThickness(R * r, L * r) + # reshape the cap at the end of the stroke + q, attr = buffer[-2] + p, attr = buffer[-1] + d = p - q + d = d / d.length * caplen_end + n = 1.0 / nverts_end + R, L = attr.getThicknessRL() + for i in range(nverts_end): + t = (nverts_end - i) * n + stroke[-i-1].setPoint(p + d * t) + r = self.round_cap_thickness((nverts_end - i + 1) * n) + stroke[-i-1].setAttribute(attr) + stroke[-i-1].attribute().setThickness(R * r, L * r) + +class SquareCapShader(StrokeShader): + def shade(self, stroke): + # save the location and attribute of stroke vertices + buffer = [] + for sv in iter_stroke_vertices(stroke): + buffer.append((sv.getPoint(), sv.attribute())) + # calculate the number of additional vertices to form caps + R, L = stroke[0].attribute().getThicknessRL() + caplen_beg = (R + L) / 2.0 + nverts_beg = 1 + R, L = stroke[-1].attribute().getThicknessRL() + caplen_end = (R + L) / 2.0 + nverts_end = 1 + # increase the total number of stroke vertices + nverts = stroke.strokeVerticesSize() + stroke.Resample(nverts + nverts_beg + nverts_end) + # restore the location and attribute of the original vertices + for i in range(nverts): + p, attr = buffer[i] + stroke[nverts_beg + i].setPoint(p) + stroke[nverts_beg + i].setAttribute(attr) + # reshape the cap at the beginning of the stroke + q, attr = buffer[1] + p, attr = buffer[0] + d = p - q + stroke[0].setPoint(p + d / d.length * caplen_beg) + stroke[0].setAttribute(attr) + # reshape the cap at the end of the stroke + q, attr = buffer[-2] + p, attr = buffer[-1] + d = p - q + stroke[-1].setPoint(p + d / d.length * caplen_beg) + stroke[-1].setAttribute(attr) + # main function for parameter processing def process(layer_name, lineset_name): @@ -372,7 +466,12 @@ def process(layer_name, lineset_name): upred = TrueUP1D() Operators.select(upred) # join feature edges - Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) # FIXME + if linestyle.same_object: + bpred = SameShapeIdBP1D() + chaining_iterator = ChainPredicateIterator(upred, bpred) + else: + chaining_iterator = ChainSilhouetteIterator() + Operators.bidirectionalChain(chaining_iterator, NotUP1D(upred)) # prepare a list of stroke shaders color = linestyle.color shaders_list = [ @@ -422,5 +521,9 @@ def process(layer_name, lineset_name): shaders_list.append(ThicknessDistanceFromObjectShader( m.blend, m.influence, m.mapping, m.invert, m.curve, m.target, m.range_min, m.range_max, m.value_min, m.value_max)) + if linestyle.caps == "ROUND": + shaders_list.append(RoundCapShader()) + elif linestyle.caps == "SQUARE": + shaders_list.append(SquareCapShader()) # create strokes using the shaders list Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/ui/properties_render.py b/release/scripts/ui/properties_render.py index af59e29c0ca..4ff9a949d99 100644 --- a/release/scripts/ui/properties_render.py +++ b/release/scripts/ui/properties_render.py @@ -409,7 +409,11 @@ class RENDER_PT_freestyle_linestyle(RenderButtonsPanel, bpy.types.Panel): for modifier in linestyle.thickness_modifiers: self.draw_thickness_modifier(context, modifier) elif linestyle.panel == "STROKES": - pass + col.label(text="Chaining:") + col.prop(linestyle, "same_object") + col.label(text="Caps:") + sub = col.row(align=True) + sub.prop(linestyle, "caps", expand=True) elif linestyle.panel == "DISTORT": pass elif linestyle.panel == "MISC": diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index ef4ce16328f..ba2e150deac 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -62,6 +62,8 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle) linestyle->color_modifiers.first = linestyle->color_modifiers.last = NULL; linestyle->alpha_modifiers.first = linestyle->alpha_modifiers.last = NULL; linestyle->thickness_modifiers.first = linestyle->thickness_modifiers.last = NULL; + + linestyle->caps = LS_CAPS_BUTT; } FreestyleLineStyle *FRS_new_linestyle(char *name, struct Main *main) diff --git a/source/blender/makesdna/DNA_linestyle_types.h b/source/blender/makesdna/DNA_linestyle_types.h index a04cbb8c79d..3deef684e3d 100644 --- a/source/blender/makesdna/DNA_linestyle_types.h +++ b/source/blender/makesdna/DNA_linestyle_types.h @@ -179,7 +179,13 @@ typedef struct LineStyleThicknessModifier_DistanceFromObject { #define LS_PANEL_MISC 6 /* FreestyleLineStyle::flag */ -#define LS_DS_EXPAND 1 /* for animation editors */ +#define LS_DS_EXPAND 1 /* for animation editors */ +#define LS_SAME_OBJECT 2 + +/* FreestyleLineStyle::caps */ +#define LS_CAPS_BUTT 1 +#define LS_CAPS_ROUND 2 +#define LS_CAPS_SQUARE 3 typedef struct FreestyleLineStyle { ID id; @@ -187,9 +193,8 @@ typedef struct FreestyleLineStyle { float r, g, b, alpha; float thickness; - int flag; + int flag, caps; int panel; /* for UI */ - int pad1; ListBase color_modifiers; ListBase alpha_modifiers; diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c index 1aa7b71af2c..9867c1ed9c6 100644 --- a/source/blender/makesrna/intern/rna_linestyle.c +++ b/source/blender/makesrna/intern/rna_linestyle.c @@ -400,6 +400,11 @@ static void rna_def_linestyle(BlenderRNA *brna) {LS_PANEL_DISTORT, "DISTORT", 0, "Distort", "Show the panel for stroke distortion."}, {LS_PANEL_MISC, "MISC", 0, "Misc", "Show the panel for miscellaneous options."}, {0, NULL, 0, NULL, NULL}}; + static EnumPropertyItem cap_items[] = { + {LS_CAPS_BUTT, "BUTT", 0, "Butt", "Butt cap (flat)."}, + {LS_CAPS_ROUND, "ROUND", 0, "Round", "Round cap (half-circle)."}, + {LS_CAPS_SQUARE, "SQUARE", 0, "Square", "Square cap (flat and extended)."}, + {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "FreestyleLineStyle", "ID"); RNA_def_struct_ui_text(srna, "Freestyle Line Style", "Freestyle line style, reusable by multiple line sets"); @@ -444,6 +449,17 @@ static void rna_def_linestyle(BlenderRNA *brna) RNA_def_property_struct_type(prop, "LineStyleThicknessModifier"); RNA_def_property_ui_text(prop, "Thickness Modifiers", "List of line thickness modifiers."); + prop= RNA_def_property(srna, "same_object", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_SAME_OBJECT); + RNA_def_property_ui_text(prop, "Same Object", "if true, only feature edges of the same object are joined."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "caps", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "caps"); + RNA_def_property_enum_items(prop, cap_items); + RNA_def_property_ui_text(prop, "Cap", "Select the shape of both ends of strokes."); + RNA_def_property_update(prop, NC_SCENE, NULL); + } void RNA_def_linestyle(BlenderRNA *brna) |