New feature edge selection criterion based on object groups.
The Freestyle tab in the Render buttons has a couple of new options "Group" and "Group Negation". The Group option specifies a group of objects (defined through the Groups tab in the Object buttons), while the Group Negation value is either INCLUSIVE or EXCLUSIVE. If INCLUSIVE, feature edges belonging to some object in the group are selected. Otherwise, those feature edges not belonging to any object in the group are selected.
This commit is contained in:
@@ -299,6 +299,19 @@ def join_unary_predicates(upred_list, bpred):
|
||||
upred = bpred(upred, p)
|
||||
return upred
|
||||
|
||||
class ObjectNamesUP1D(UnaryPredicate1D):
|
||||
def __init__(self, names, negative):
|
||||
UnaryPredicate1D.__init__(self)
|
||||
self._names = names
|
||||
self._negative = negative
|
||||
def getName(self):
|
||||
return "ObjectNamesUP1D"
|
||||
def __call__(self, viewEdge):
|
||||
found = viewEdge.viewShape().getName() in self._names
|
||||
if self._negative:
|
||||
return not found
|
||||
return found
|
||||
|
||||
# Stroke caps
|
||||
|
||||
def iter_stroke_vertices(stroke):
|
||||
@@ -506,6 +519,12 @@ def process(layer_name, lineset_name):
|
||||
if lineset.edge_type_negation == "EXCLUSIVE":
|
||||
upred = NotUP1D(upred)
|
||||
selection_criteria.append(upred)
|
||||
# prepare selection criteria by group of objects
|
||||
if lineset.select_by_group:
|
||||
if lineset.group is not None and len(lineset.group.objects) > 0:
|
||||
names = dict((ob.name, True) for ob in lineset.group.objects)
|
||||
upred = ObjectNamesUP1D(names, lineset.group_negation == 'EXCLUSIVE')
|
||||
selection_criteria.append(upred)
|
||||
# do feature edge selection
|
||||
upred = join_unary_predicates(selection_criteria, AndUP1D)
|
||||
if upred is None:
|
||||
|
||||
@@ -220,20 +220,19 @@ class RENDER_PT_freestyle(RenderButtonsPanel, bpy.types.Panel):
|
||||
|
||||
if lineset:
|
||||
col.prop(lineset, "name")
|
||||
col.prop(lineset, "select_by_visibility")
|
||||
col.prop(lineset, "select_by_edge_types")
|
||||
|
||||
col.prop(lineset, "select_by_visibility")
|
||||
if lineset.select_by_visibility:
|
||||
col.label(text="Visibility:")
|
||||
sub = col.row(align=True)
|
||||
sub.prop(lineset, "visibility", expand=True)
|
||||
if lineset.visibility == "RANGE":
|
||||
sub = col.row(align=True)
|
||||
sub.prop(lineset, "qi_start")
|
||||
sub.prop(lineset, "qi_end")
|
||||
col.separator() # XXX
|
||||
|
||||
col.prop(lineset, "select_by_edge_types")
|
||||
if lineset.select_by_edge_types:
|
||||
col.label(text="Edge Types:")
|
||||
row = col.row()
|
||||
row.prop(lineset, "edge_type_negation", expand=True)
|
||||
row = col.row()
|
||||
@@ -251,6 +250,13 @@ class RENDER_PT_freestyle(RenderButtonsPanel, bpy.types.Panel):
|
||||
sub = row.column()
|
||||
sub.prop(lineset, "select_contour")
|
||||
sub.prop(lineset, "select_external_contour")
|
||||
col.separator() # XXX
|
||||
|
||||
col.prop(lineset, "select_by_group")
|
||||
if lineset.select_by_group:
|
||||
col.prop(lineset, "group")
|
||||
row = col.row()
|
||||
row.prop(lineset, "group_negation", expand=True)
|
||||
|
||||
else: # freestyle.mode == "SCRIPT"
|
||||
|
||||
|
||||
@@ -4243,6 +4243,7 @@ static void lib_link_scene(FileData *fd, Main *main)
|
||||
srl->light_override= newlibadr_us(fd, sce->id.lib, srl->light_override);
|
||||
for(fls=srl->freestyleConfig.linesets.first; fls; fls= fls->next) {
|
||||
fls->linestyle= newlibadr_us(fd, sce->id.lib, fls->linestyle);
|
||||
fls->group= newlibadr_us(fd, sce->id.lib, fls->group);
|
||||
}
|
||||
}
|
||||
/*Game Settings: Dome Warp Text*/
|
||||
|
||||
@@ -1895,6 +1895,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
|
||||
for(fls= srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
|
||||
writestruct(wd, DATA, "FreestyleLineSet", 1, fls);
|
||||
writestruct(wd, DATA, "FreestyleLineStyle", 1, fls->linestyle);
|
||||
writestruct(wd, DATA, "Group", 1, fls->group);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -444,7 +444,7 @@ extern "C" {
|
||||
lineset->qi_start = 0;
|
||||
lineset->qi_end = 100;
|
||||
lineset->edge_types = 0;
|
||||
lineset->objects.first = lineset->objects.last = NULL;
|
||||
lineset->group = NULL;
|
||||
if (lineset_index > 0)
|
||||
sprintf(lineset->name, "LineSet %i", lineset_index+1);
|
||||
else
|
||||
|
||||
@@ -50,10 +50,12 @@ struct FreestyleLineStyle;
|
||||
#define FREESTYLE_LINESET_ENABLED 2
|
||||
#define FREESTYLE_LINESET_FE_NOT 4
|
||||
#define FREESTYLE_LINESET_FE_AND 8
|
||||
#define FREESTYLE_LINESET_GR_NOT 16
|
||||
|
||||
/* FreestyleLineSet::selection */
|
||||
#define FREESTYLE_SEL_VISIBILITY 1
|
||||
#define FREESTYLE_SEL_EDGE_TYPES 2
|
||||
#define FREESTYLE_SEL_GROUP 4
|
||||
|
||||
/* FreestyleLineSet::fedge_types */
|
||||
#define FREESTYLE_FE_SILHOUETTE 1
|
||||
@@ -82,11 +84,10 @@ typedef struct FreestyleLineSet {
|
||||
short pad1;
|
||||
int qi_start, qi_end;
|
||||
int edge_types; /* feature edge types */
|
||||
struct Group *group; /* group of target objects */
|
||||
|
||||
struct FreestyleLineStyle *linestyle;
|
||||
|
||||
ListBase objects; /* target objects on which stylized lines are drawn */
|
||||
|
||||
} FreestyleLineSet;
|
||||
|
||||
typedef struct FreestyleModuleConfig {
|
||||
|
||||
@@ -1641,16 +1641,21 @@ static void rna_def_freestyle_settings(BlenderRNA *brna)
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem negation_items[] = {
|
||||
static EnumPropertyItem edge_type_negation_items[] = {
|
||||
{0, "INCLUSIVE", 0, "Inclusive", "Select feature edges satisfying the given edge type conditions."},
|
||||
{FREESTYLE_LINESET_FE_NOT, "EXCLUSIVE", 0, "Exclusive", "Select feature edges not satisfying the given edge type conditions."},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem combination_items[] = {
|
||||
static EnumPropertyItem edge_type_combination_items[] = {
|
||||
{0, "OR", 0, "Logical OR", "Combine feature edge type conditions by logical OR (logical disjunction)."},
|
||||
{FREESTYLE_LINESET_FE_AND, "AND", 0, "Logical AND", "Combine feature edge type conditions by logical AND (logical conjunction)."},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem group_negation_items[] = {
|
||||
{0, "INCLUSIVE", 0, "Inclusive", "Select feature edges belonging to some object in the group."},
|
||||
{FREESTYLE_LINESET_GR_NOT, "EXCLUSIVE", 0, "Exclusive", "Select feature edges not belonging to any object in the group."},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem freestyle_ui_mode_items[] = {
|
||||
{FREESTYLE_CONTROL_SCRIPT_MODE, "SCRIPT", 0, "Python Scripting Mode", "Advanced mode for using style modules in Python"},
|
||||
{FREESTYLE_CONTROL_EDITOR_MODE, "EDITOR", 0, "Parameter Editor Mode", "Basic mode for interactive style parameter editing"},
|
||||
@@ -1697,22 +1702,35 @@ static void rna_def_freestyle_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Selection by Edge Types", "Select feature edges based on edge types.");
|
||||
RNA_def_property_update(prop, NC_SCENE, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "select_by_group", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_GROUP);
|
||||
RNA_def_property_ui_text(prop, "Selection by Group", "Select feature edges based on a group of objects.");
|
||||
RNA_def_property_update(prop, NC_SCENE, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "edge_type_negation", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
|
||||
RNA_def_property_enum_items(prop, negation_items);
|
||||
RNA_def_property_enum_items(prop, edge_type_negation_items);
|
||||
RNA_def_property_ui_text(prop, "Edge Type Negation", "Set the negation operation for conditions on feature edge types.");
|
||||
RNA_def_property_update(prop, NC_SCENE, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "edge_type_combination", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
|
||||
RNA_def_property_enum_items(prop, combination_items);
|
||||
RNA_def_property_enum_items(prop, edge_type_combination_items);
|
||||
RNA_def_property_ui_text(prop, "Edge Type Combination", "Set the combination operation for conditions on feature edge types.");
|
||||
RNA_def_property_update(prop, NC_SCENE, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "objects", NULL);
|
||||
RNA_def_property_struct_type(prop, "Object");
|
||||
RNA_def_property_ui_text(prop, "Target Objects", "A list of objects on which stylized lines are drawn.");
|
||||
prop= RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "group");
|
||||
RNA_def_property_struct_type(prop, "Group");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Group", "A group of objects based on which feature edges are selected.");
|
||||
RNA_def_property_update(prop, NC_SCENE, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "group_negation", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
|
||||
RNA_def_property_enum_items(prop, group_negation_items);
|
||||
RNA_def_property_ui_text(prop, "Edge Type Negation", "Set the negation operation for conditions on feature edge types.");
|
||||
RNA_def_property_update(prop, NC_SCENE, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "select_silhouette", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_SILHOUETTE);
|
||||
|
||||
Reference in New Issue
Block a user