Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/freestyle/style_modules/parameter_editor.py160
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py6
-rw-r--r--source/blender/blenkernel/intern/linestyle.c4
-rw-r--r--source/blender/blenloader/intern/readfile.c4
-rw-r--r--source/blender/makesdna/DNA_linestyle_types.h8
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c18
6 files changed, 163 insertions, 37 deletions
diff --git a/release/scripts/freestyle/style_modules/parameter_editor.py b/release/scripts/freestyle/style_modules/parameter_editor.py
index d0999782337..caf262e1397 100644
--- a/release/scripts/freestyle/style_modules/parameter_editor.py
+++ b/release/scripts/freestyle/style_modules/parameter_editor.py
@@ -88,6 +88,80 @@ class CurveMappingModifier(ScalarBlendModifier):
def evaluate(self, t):
return self.__mapping(t)
+class ThicknessModifierMixIn:
+ def __init__(self):
+ scene = Freestyle.getCurrentScene()
+ self.__persp_camera = (scene.camera.data.type == "PERSP")
+ def set_thickness(self, sv, outer, inner):
+ fe = sv.A().getFEdge(sv.B())
+ nature = fe.getNature()
+ if (nature & Nature.BORDER):
+ if self.__persp_camera:
+ point = -sv.getPoint3D()
+ point.normalize()
+ dir = point.dot(fe.normalB())
+ else:
+ dir = fe.normalB().z
+ if dir < 0.0: # the back side is visible
+ outer, inner = inner, outer
+ elif (nature & Nature.SILHOUETTE):
+ if fe.isSmooth(): # TODO more tests needed
+ outer, inner = inner, outer
+ else:
+ outer = inner = (outer + inner) / 2
+ sv.attribute().setThickness(outer, inner)
+
+class ThicknessBlenderMixIn(ThicknessModifierMixIn):
+ def __init__(self, position, ratio):
+ ThicknessModifierMixIn.__init__(self)
+ self.__position = position
+ self.__ratio = ratio
+ def blend_thickness(self, outer, inner, v):
+ if self.__position == "CENTER":
+ outer = self.__modifier.blend(outer, v / 2)
+ inner = self.__modifier.blend(inner, v / 2)
+ elif self.__position == "INSIDE":
+ inner = self.__modifier.blend(inner, v)
+ elif self.__position == "OUTSIDE":
+ outer = self.__modifier.blend(outer, v)
+ elif self.__position == "RELATIVE":
+ outer = self.__modifier.blend(outer, v * self.ratio)
+ inner = self.__modifier.blend(inner, v * (1 - self.ratio))
+ else:
+ raise ValueError("unknown thickness position: " + self.__position)
+ return outer, inner
+
+class BaseColorShader(ConstantColorShader):
+ def getName(self):
+ return "BaseColorShader"
+
+class BaseThicknessShader(StrokeShader, ThicknessModifierMixIn):
+ def __init__(self, thickness, position, ratio):
+ StrokeShader.__init__(self)
+ ThicknessModifierMixIn.__init__(self)
+ if position == "CENTER":
+ self.__outer = thickness / 2
+ self.__inner = thickness / 2
+ elif position == "INSIDE":
+ self.__outer = 0
+ self.__inner = thickness
+ elif position == "OUTSIDE":
+ self.__outer = thickness
+ self.__inner = 0
+ elif position == "RELATIVE":
+ self.__outer = thickness * ratio
+ self.__inner = thickness * (1 - ratio)
+ else:
+ raise ValueError("unknown thickness position: " + self.position)
+ def getName(self):
+ return "BaseThicknessShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ sv = it.getObject()
+ self.set_thickness(sv, self.__outer, self.__inner)
+ it.increment()
+
# Along Stroke modifiers
def iter_t2d_along_stroke(stroke):
@@ -125,8 +199,10 @@ class AlphaAlongStrokeShader(CurveMappingModifier):
c = self.blend(a, b)
attr.setAlpha(c)
-class ThicknessAlongStrokeShader(CurveMappingModifier):
- def __init__(self, blend, influence, mapping, invert, curve, value_min, value_max):
+class ThicknessAlongStrokeShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, mapping, invert, curve, value_min, value_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
self.__value_min = value_min
self.__value_max = value_max
@@ -134,12 +210,11 @@ class ThicknessAlongStrokeShader(CurveMappingModifier):
return "ThicknessAlongStrokeShader"
def shade(self, stroke):
for it, t in iter_t2d_along_stroke(stroke):
- attr = it.getObject().attribute()
- a = attr.getThicknessRL()
- a = a[0] + a[1]
+ sv = it.getObject()
+ a = sv.attribute().getThicknessRL()
b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
- c = self.blend(a, b)
- attr.setThickness(c/2, c/2)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
# Distance from Camera modifiers
@@ -188,8 +263,10 @@ class AlphaDistanceFromCameraShader(CurveMappingModifier):
c = self.blend(a, b)
attr.setAlpha(c)
-class ThicknessDistanceFromCameraShader(CurveMappingModifier):
- def __init__(self, blend, influence, mapping, invert, curve, range_min, range_max, value_min, value_max):
+class ThicknessDistanceFromCameraShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, mapping, invert, curve, range_min, range_max, value_min, value_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
self.__range_min = range_min
self.__range_max = range_max
@@ -199,12 +276,11 @@ class ThicknessDistanceFromCameraShader(CurveMappingModifier):
return "ThicknessDistanceFromCameraShader"
def shade(self, stroke):
for it, t in iter_distance_from_camera(stroke, self.__range_min, self.__range_max):
- attr = it.getObject().attribute()
- a = attr.getThicknessRL()
- a = a[0] + a[1]
+ sv = it.getObject()
+ a = sv.attribute().getThicknessRL()
b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
- c = self.blend(a, b)
- attr.setThickness(c/2, c/2)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
# Distance from Object modifiers
@@ -263,8 +339,10 @@ class AlphaDistanceFromObjectShader(CurveMappingModifier):
c = self.blend(a, b)
attr.setAlpha(c)
-class ThicknessDistanceFromObjectShader(CurveMappingModifier):
- def __init__(self, blend, influence, mapping, invert, curve, target, range_min, range_max, value_min, value_max):
+class ThicknessDistanceFromObjectShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, mapping, invert, curve, target, range_min, range_max, value_min, value_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
self.__target = target
self.__range_min = range_min
@@ -277,12 +355,11 @@ class ThicknessDistanceFromObjectShader(CurveMappingModifier):
if self.__target is None:
return
for it, t in iter_distance_from_object(stroke, self.__target, self.__range_min, self.__range_max):
- attr = it.getObject().attribute()
- a = attr.getThicknessRL()
- a = a[0] + a[1]
+ sv = it.getObject()
+ a = sv.attribute().getThicknessRL()
b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
- c = self.blend(a, b)
- attr.setThickness(c/2, c/2)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
# Material modifiers
@@ -376,8 +453,10 @@ class AlphaMaterialShader(CurveMappingModifier):
c = self.blend(a, b)
attr.setAlpha(c)
-class ThicknessMaterialShader(CurveMappingModifier):
- def __init__(self, blend, influence, mapping, invert, curve, material_attr, value_min, value_max):
+class ThicknessMaterialShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, mapping, invert, curve, material_attr, value_min, value_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
self.__material_attr = material_attr
self.__value_min = value_min
@@ -386,17 +465,18 @@ class ThicknessMaterialShader(CurveMappingModifier):
return "ThicknessMaterialShader"
def shade(self, stroke):
for it, t in iter_material_value(stroke, self.__material_attr):
- attr = it.getObject().attribute()
- a = attr.getThicknessRL()
- a = a[0] + a[1]
+ sv = it.getObject()
+ a = sv.attribute().getThicknessRL()
b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
- c = self.blend(a, b)
- attr.setThickness(c/2, c/2)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
# Calligraphic thickness modifier
-class CalligraphicThicknessShader(ScalarBlendModifier):
- def __init__(self, blend, influence, orientation, min_thickness, max_thickness):
+class CalligraphicThicknessShader(ThicknessBlenderMixIn, ScalarBlendModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, orientation, min_thickness, max_thickness):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
ScalarBlendModifier.__init__(self, blend, influence)
rad = orientation / 180.0 * math.pi
self.__orientation = mathutils.Vector((math.cos(rad), math.sin(rad)))
@@ -410,13 +490,12 @@ class CalligraphicThicknessShader(ScalarBlendModifier):
orthDir = mathutils.Vector((-dir.y, dir.x))
orthDir.normalize()
fac = abs(orthDir * self.__orientation)
- attr = it.getObject().attribute()
- a = attr.getThicknessRL()
- a = a[0] + a[1]
+ sv = it.getObject()
+ a = sv.attribute().getThicknessRL()
b = self.__min_thickness + fac * (self.__max_thickness - self.__min_thickness)
b = max(b, 0.0)
- c = self.blend(a, b)
- attr.setThickness(c/2, c/2)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
it.increment()
# Geometry modifiers
@@ -1132,8 +1211,10 @@ def process(layer_name, lineset_name):
shaders_list.append(Transform2DShader(
m.pivot, m.scale_x, m.scale_y, m.angle, m.pivot_u, m.pivot_x, m.pivot_y))
color = linestyle.color
- shaders_list.append(ConstantColorShader(color.r, color.g, color.b, linestyle.alpha))
- shaders_list.append(ConstantThicknessShader(linestyle.thickness))
+ shaders_list.append(BaseColorShader(color.r, color.g, color.b, linestyle.alpha))
+ shaders_list.append(BaseThicknessShader(linestyle.thickness,
+ linestyle.thickness_position,
+ linestyle.thickness_ratio))
for m in linestyle.color_modifiers:
if not m.use:
continue
@@ -1175,22 +1256,27 @@ def process(layer_name, lineset_name):
continue
if m.type == "ALONG_STROKE":
shaders_list.append(ThicknessAlongStrokeShader(
+ linestyle.thickness_position, linestyle.thickness_ratio,
m.blend, m.influence, m.mapping, m.invert, m.curve,
m.value_min, m.value_max))
elif m.type == "DISTANCE_FROM_CAMERA":
shaders_list.append(ThicknessDistanceFromCameraShader(
+ linestyle.thickness_position, linestyle.thickness_ratio,
m.blend, m.influence, m.mapping, m.invert, m.curve,
m.range_min, m.range_max, m.value_min, m.value_max))
elif m.type == "DISTANCE_FROM_OBJECT":
shaders_list.append(ThicknessDistanceFromObjectShader(
+ linestyle.thickness_position, linestyle.thickness_ratio,
m.blend, m.influence, m.mapping, m.invert, m.curve, m.target,
m.range_min, m.range_max, m.value_min, m.value_max))
elif m.type == "MATERIAL":
shaders_list.append(ThicknessMaterialShader(
+ linestyle.thickness_position, linestyle.thickness_ratio,
m.blend, m.influence, m.mapping, m.invert, m.curve,
m.material_attr, m.value_min, m.value_max))
elif m.type == "CALLIGRAPHY":
shaders_list.append(CalligraphicThicknessShader(
+ linestyle.thickness_position, linestyle.thickness_ratio,
m.blend, m.influence,
m.orientation, m.min_thickness, m.max_thickness))
if linestyle.caps == "ROUND":
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index d6af8207553..d38363afafa 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -696,6 +696,12 @@ class RENDER_PT_freestyle_linestyle(RenderButtonsPanel, Panel):
col.label(text="Base Thickness:")
col.prop(linestyle, "thickness")
col = layout.column()
+ row = col.row()
+ row.prop(linestyle, "thickness_position", expand=True)
+ row = col.row()
+ row.prop(linestyle, "thickness_ratio")
+ row.enabled = linestyle.thickness_position == "RELATIVE"
+ col = layout.column()
col.label(text="Modifiers:")
col.operator_menu_enum("scene.freestyle_thickness_modifier_add", "type", text="Add Modifier")
for modifier in linestyle.thickness_modifiers:
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index dcacfeea5bc..b2c2cb27e31 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -75,6 +75,8 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle)
linestyle->r = linestyle->g = linestyle->b = 0.0;
linestyle->alpha = 1.0;
linestyle->thickness = 1.0;
+ linestyle->thickness_position = LS_THICKNESS_CENTER;
+ linestyle->thickness_ratio = 0.5f;
linestyle->chaining = LS_CHAINING_PLAIN;
linestyle->rounds = 3;
linestyle->min_angle = 0.0f;
@@ -135,6 +137,8 @@ FreestyleLineStyle *FRS_copy_linestyle(FreestyleLineStyle *linestyle)
new_linestyle->b = linestyle->b;
new_linestyle->alpha = linestyle->alpha;
new_linestyle->thickness = linestyle->thickness;
+ new_linestyle->thickness_position = linestyle->thickness_position;
+ new_linestyle->thickness_ratio = linestyle->thickness_ratio;
new_linestyle->flag = linestyle->flag;
new_linestyle->caps = linestyle->caps;
new_linestyle->chaining = linestyle->chaining;
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index ccff9ce02ff..dbb09022ddb 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -13566,6 +13566,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
for(linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
+ if (linestyle->thickness_position == 0) {
+ linestyle->thickness_position= LS_THICKNESS_CENTER;
+ linestyle->thickness_ratio= 0.5f;
+ }
if (linestyle->chaining == 0)
linestyle->chaining= LS_CHAINING_PLAIN;
if (linestyle->rounds == 0)
diff --git a/source/blender/makesdna/DNA_linestyle_types.h b/source/blender/makesdna/DNA_linestyle_types.h
index 1c82443e357..9ffb53e83b6 100644
--- a/source/blender/makesdna/DNA_linestyle_types.h
+++ b/source/blender/makesdna/DNA_linestyle_types.h
@@ -400,12 +400,20 @@ typedef struct LineStyleThicknessModifier_Calligraphy {
#define LS_CAPS_ROUND 2
#define LS_CAPS_SQUARE 3
+/* FreestyleLineStyle::thickness_position */
+#define LS_THICKNESS_CENTER 1
+#define LS_THICKNESS_INSIDE 2
+#define LS_THICKNESS_OUTSIDE 3
+#define LS_THICKNESS_RELATIVE 4 /* thickness_ratio is used */
+
typedef struct FreestyleLineStyle {
ID id;
struct AnimData *adt;
float r, g, b, alpha;
float thickness;
+ int thickness_position;
+ float thickness_ratio;
int flag, caps;
int chaining;
unsigned int rounds;
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
index dc1942b23b4..abb715f2471 100644
--- a/source/blender/makesrna/intern/rna_linestyle.c
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -875,6 +875,12 @@ static void rna_def_linestyle(BlenderRNA *brna)
{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}};
+ static EnumPropertyItem thickness_position_items[] = {
+ {LS_THICKNESS_CENTER, "CENTER", 0, "Center", "Stroke is centered along stroke geometry"},
+ {LS_THICKNESS_INSIDE, "INSIDE", 0, "Inside", "Stroke is drawn inside stroke geometry"},
+ {LS_THICKNESS_OUTSIDE, "OUTSIDE", 0, "Outside", "Stroke is drawn outside stroke geometry"},
+ {LS_THICKNESS_RELATIVE, "RELATIVE", 0, "Relative", "Stroke thinkness is split by a user-defined ratio"},
+ {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");
@@ -904,6 +910,18 @@ static void rna_def_linestyle(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Thickness", "Base line thickness, possibly modified by line thickness modifiers");
RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+ prop= RNA_def_property(srna, "thickness_position", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "thickness_position");
+ RNA_def_property_enum_items(prop, thickness_position_items);
+ RNA_def_property_ui_text(prop, "Thickness Position", "Select the position of stroke thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "thickness_ratio", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "thickness_ratio");
+ RNA_def_property_range(prop, 0.f, 1.f);
+ RNA_def_property_ui_text(prop, "Thickness Ratio", "A number between 0 (inside) and 1 (outside) specifying the relative position of stroke thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
prop= RNA_def_property(srna, "color_modifiers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "color_modifiers", NULL);
RNA_def_property_struct_type(prop, "LineStyleColorModifier");