forked from bartvdbraak/blender
Freestyle: New line style options for sorting and chain selection.
The following two sort keys are added for sorting chains. * Projected X - Sort by the projected X value in the image coordinate system. * Projected Y - Sort by the projected Y value in the image coordinate system. A new line style option for the selection of first N chains is also added. Moreover, the chain sorting and chain selection operations are now executed in this order instead of the reverse order used previously. The UI has also changed accordingly. This functional change is backward compatible and won't result in visual differences.
This commit is contained in:
parent
55aa42ad6f
commit
2cb134be2b
@ -82,6 +82,8 @@ __all__ = (
|
||||
"pyNatureUP1D",
|
||||
"pyParameterUP0D",
|
||||
"pyParameterUP0DGoodOne",
|
||||
"pyProjectedXBP1D",
|
||||
"pyProjectedYBP1D",
|
||||
"pyShapeIdListUP1D",
|
||||
"pyShapeIdUP1D",
|
||||
"pyShuffleBP1D",
|
||||
@ -135,6 +137,8 @@ from freestyle.functions import (
|
||||
GetCurvilinearAbscissaF0D,
|
||||
GetDirectionalViewMapDensityF1D,
|
||||
GetOccludersF1D,
|
||||
GetProjectedXF1D,
|
||||
GetProjectedYF1D,
|
||||
GetProjectedZF1D,
|
||||
GetShapeF1D,
|
||||
GetSteerableViewMapDensityF1D,
|
||||
@ -596,6 +600,24 @@ class pyZBP1D(BinaryPredicate1D):
|
||||
return (self.func(i1) > self.func(i2))
|
||||
|
||||
|
||||
class pyProjectedXBP1D(BinaryPredicate1D):
|
||||
def __init__(self, iType=IntegrationType.MEAN):
|
||||
BinaryPredicate1D.__init__(self)
|
||||
self.func = GetProjectedXF1D(iType)
|
||||
|
||||
def __call__(self, i1, i2):
|
||||
return (self.func(i1) > self.func(i2))
|
||||
|
||||
|
||||
class pyProjectedYBP1D(BinaryPredicate1D):
|
||||
def __init__(self, iType=IntegrationType.MEAN):
|
||||
BinaryPredicate1D.__init__(self)
|
||||
self.func = GetProjectedYF1D(iType)
|
||||
|
||||
def __call__(self, i1, i2):
|
||||
return (self.func(i1) > self.func(i2))
|
||||
|
||||
|
||||
class pyZDiscontinuityBP1D(BinaryPredicate1D):
|
||||
def __init__(self, iType=IntegrationType.MEAN):
|
||||
BinaryPredicate1D.__init__(self)
|
||||
|
@ -62,7 +62,10 @@ from freestyle.predicates import (
|
||||
TrueBP1D,
|
||||
TrueUP1D,
|
||||
WithinImageBoundaryUP1D,
|
||||
pyNFirstUP1D,
|
||||
pyNatureUP1D,
|
||||
pyProjectedXBP1D,
|
||||
pyProjectedYBP1D,
|
||||
pyZBP1D,
|
||||
)
|
||||
from freestyle.shaders import (
|
||||
@ -1006,11 +1009,6 @@ def process(layer_name, lineset_name):
|
||||
Operators.sequential_split(SplitPatternStartingUP0D(controller),
|
||||
SplitPatternStoppingUP0D(controller),
|
||||
sampling)
|
||||
# select chains
|
||||
if linestyle.use_length_min or linestyle.use_length_max:
|
||||
length_min = linestyle.length_min if linestyle.use_length_min else None
|
||||
length_max = linestyle.length_max if linestyle.use_length_max else None
|
||||
Operators.select(LengthThresholdUP1D(length_min, length_max))
|
||||
# sort selected chains
|
||||
if linestyle.use_sorting:
|
||||
integration = integration_types.get(linestyle.integration_type, IntegrationType.MEAN)
|
||||
@ -1018,9 +1016,20 @@ def process(layer_name, lineset_name):
|
||||
bpred = pyZBP1D(integration)
|
||||
elif linestyle.sort_key == '2D_LENGTH':
|
||||
bpred = Length2DBP1D()
|
||||
elif linestyle.sort_key == 'PROJECTED_X':
|
||||
bpred = pyProjectedXBP1D(integration)
|
||||
elif linestyle.sort_key == 'PROJECTED_Y':
|
||||
bpred = pyProjectedYBP1D(integration)
|
||||
if linestyle.sort_order == 'REVERSE':
|
||||
bpred = NotBP1D(bpred)
|
||||
Operators.sort(bpred)
|
||||
# select chains
|
||||
if linestyle.use_length_min or linestyle.use_length_max:
|
||||
length_min = linestyle.length_min if linestyle.use_length_min else None
|
||||
length_max = linestyle.length_max if linestyle.use_length_max else None
|
||||
Operators.select(LengthThresholdUP1D(length_min, length_max))
|
||||
if linestyle.use_chain_count:
|
||||
Operators.select(pyNFirstUP1D(linestyle.chain_count))
|
||||
# prepare a list of stroke shaders
|
||||
shaders_list = []
|
||||
for m in linestyle.geometry_modifiers:
|
||||
|
@ -579,6 +579,20 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
|
||||
sub.prop(linestyle, "split_dash3", text="D3")
|
||||
sub.prop(linestyle, "split_gap3", text="G3")
|
||||
|
||||
## Sorting
|
||||
layout.prop(linestyle, "use_sorting", text="Sorting:")
|
||||
col = layout.column()
|
||||
col.active = linestyle.use_sorting
|
||||
row = col.row(align=True)
|
||||
row.prop(linestyle, "sort_key", text="")
|
||||
sub = row.row()
|
||||
sub.active = linestyle.sort_key in {'DISTANCE_FROM_CAMERA',
|
||||
'PROJECTED_X',
|
||||
'PROJECTED_Y'}
|
||||
sub.prop(linestyle, "integration_type", text="")
|
||||
row = col.row(align=True)
|
||||
row.prop(linestyle, "sort_order", expand=True)
|
||||
|
||||
## Selection
|
||||
layout.label(text="Selection:")
|
||||
split = layout.split(align=True)
|
||||
@ -589,25 +603,18 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
|
||||
sub = row.row()
|
||||
sub.active = linestyle.use_length_min
|
||||
sub.prop(linestyle, "length_min")
|
||||
# Second column
|
||||
col = split.column()
|
||||
row = col.row(align=True)
|
||||
row.prop(linestyle, "use_length_max", text="")
|
||||
sub = row.row()
|
||||
sub.active = linestyle.use_length_max
|
||||
sub.prop(linestyle, "length_max")
|
||||
|
||||
## Sorting
|
||||
layout.prop(linestyle, "use_sorting", text="Sorting:")
|
||||
col = layout.column()
|
||||
col.active = linestyle.use_sorting
|
||||
# Second column
|
||||
col = split.column()
|
||||
row = col.row(align=True)
|
||||
row.prop(linestyle, "sort_key", text="")
|
||||
row.prop(linestyle, "use_chain_count", text="")
|
||||
sub = row.row()
|
||||
sub.active = linestyle.sort_key in {'DISTANCE_FROM_CAMERA'}
|
||||
sub.prop(linestyle, "integration_type", text="")
|
||||
row = col.row(align=True)
|
||||
row.prop(linestyle, "sort_order", expand=True)
|
||||
sub.active = linestyle.use_chain_count
|
||||
sub.prop(linestyle, "chain_count")
|
||||
|
||||
## Caps
|
||||
layout.label(text="Caps:")
|
||||
|
@ -93,6 +93,7 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle)
|
||||
linestyle->min_length = 0.0f;
|
||||
linestyle->max_length = 10000.0f;
|
||||
linestyle->split_length = 100;
|
||||
linestyle->chain_count = 10;
|
||||
linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA;
|
||||
linestyle->integration_type = LS_INTEGRATION_MEAN;
|
||||
linestyle->texstep = 1.0f;
|
||||
@ -186,6 +187,7 @@ FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle)
|
||||
new_linestyle->max_angle = linestyle->max_angle;
|
||||
new_linestyle->min_length = linestyle->min_length;
|
||||
new_linestyle->max_length = linestyle->max_length;
|
||||
new_linestyle->chain_count = linestyle->chain_count;
|
||||
new_linestyle->split_dash1 = linestyle->split_dash1;
|
||||
new_linestyle->split_gap1 = linestyle->split_gap1;
|
||||
new_linestyle->split_dash2 = linestyle->split_dash2;
|
||||
|
@ -99,6 +99,7 @@ void BLO_update_defaults_startup_blend(Main *bmain)
|
||||
linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA;
|
||||
linestyle->integration_type = LS_INTEGRATION_MEAN;
|
||||
linestyle->texstep = 1.0;
|
||||
linestyle->chain_count = 10;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -387,6 +387,7 @@ typedef struct LineStyleThicknessModifier_Calligraphy {
|
||||
#define LS_NO_SORTING (1 << 11)
|
||||
#define LS_REVERSE_ORDER (1 << 12) /* for sorting */
|
||||
#define LS_TEXTURE (1 << 13)
|
||||
#define LS_CHAIN_COUNT (1 << 14)
|
||||
|
||||
/* FreestyleLineStyle::chaining */
|
||||
#define LS_CHAINING_PLAIN 1
|
||||
@ -406,6 +407,8 @@ typedef struct LineStyleThicknessModifier_Calligraphy {
|
||||
/* FreestyleLineStyle::sort_key */
|
||||
#define LS_SORT_KEY_DISTANCE_FROM_CAMERA 1
|
||||
#define LS_SORT_KEY_2D_LENGTH 2
|
||||
#define LS_SORT_KEY_PROJECTED_X 3
|
||||
#define LS_SORT_KEY_PROJECTED_Y 4
|
||||
|
||||
/* FreestyleLineStyle::integration_type */
|
||||
#define LS_INTEGRATION_MEAN 1
|
||||
@ -428,13 +431,14 @@ typedef struct FreestyleLineStyle {
|
||||
float split_length;
|
||||
float min_angle, max_angle; /* in radians, for splitting */
|
||||
float min_length, max_length;
|
||||
unsigned int chain_count;
|
||||
unsigned short split_dash1, split_gap1;
|
||||
unsigned short split_dash2, split_gap2;
|
||||
unsigned short split_dash3, split_gap3;
|
||||
int sort_key, integration_type;
|
||||
float texstep;
|
||||
short texact, pr_texture;
|
||||
short use_nodes, pad;
|
||||
short use_nodes, pad[3];
|
||||
unsigned short dash1, gap1, dash2, gap2, dash3, gap3;
|
||||
int panel; /* for UI */
|
||||
|
||||
|
@ -1322,6 +1322,8 @@ static void rna_def_linestyle(BlenderRNA *brna)
|
||||
static EnumPropertyItem sort_key_items[] = {
|
||||
{LS_SORT_KEY_DISTANCE_FROM_CAMERA, "DISTANCE_FROM_CAMERA", 0, "Distance from Camera", "Sort by distance from camera (closer lines lie on top of further lines)"},
|
||||
{LS_SORT_KEY_2D_LENGTH, "2D_LENGTH", 0, "2D Length", "Sort by curvilinear 2D length (longer lines lie on top of shorter lines)"},
|
||||
{LS_SORT_KEY_PROJECTED_X, "PROJECTED_X", 0, "Projected X", "Sort by the projected X value in the image coordinate system"},
|
||||
{LS_SORT_KEY_PROJECTED_Y, "PROJECTED_Y", 0, "Projected Y", "Sort by the projected Y value in the image coordinate system"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
static EnumPropertyItem sort_order_items[] = {
|
||||
@ -1488,6 +1490,16 @@ static void rna_def_linestyle(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Max 2D Length", "Maximum curvilinear 2D length for the selection of chains");
|
||||
RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_chain_count", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_CHAIN_COUNT);
|
||||
RNA_def_property_ui_text(prop, "Use Chain Count", "Enable the selection of first N chains");
|
||||
RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
|
||||
|
||||
prop = RNA_def_property(srna, "chain_count", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, NULL, "chain_count");
|
||||
RNA_def_property_ui_text(prop, "Chain Count", "Chain count for the selection of first N chains");
|
||||
RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_split_pattern", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_SPLIT_PATTERN);
|
||||
RNA_def_property_ui_text(prop, "Use Split Pattern", "Enable chain splitting by dashed line patterns");
|
||||
|
Loading…
Reference in New Issue
Block a user