Freestyle: New options for sorting to arrange the stacking order of lines.
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>
Fri, 18 Apr 2014 05:59:02 +0000 (14:59 +0900)
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>
Fri, 18 Apr 2014 06:02:45 +0000 (15:02 +0900)
Line styles now have a set of new options for rearranging the stacking order of lines.
This gives artists more control to determine which lines should be drawn on top of others.
Two available sort keys are the distance from camera and curvilinear 2D length.
Since the distance of a line from camera may vary over vertices, another option called
integration type is used to compute the sort key for a line from the values computed at
individual vertices.  Available integration types are MEAN, MIN, MAX, FIRST and LAST
(see the tool tips for more detail).

release/scripts/freestyle/modules/parameter_editor.py
release/scripts/startup/bl_ui/properties_freestyle.py
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/intern/linestyle.c
source/blender/blenloader/intern/versioning_270.c
source/blender/blenloader/intern/versioning_defaults.c
source/blender/makesdna/DNA_linestyle_types.h
source/blender/makesrna/intern/rna_linestyle.c

index ce15028d0d7fd53369db68d40013364392bd8057..73ae0f4712c9f5ae96c103d022a608e8eea9c437 100644 (file)
@@ -23,6 +23,7 @@
 
 from freestyle.types import (
     BinaryPredicate1D,
 
 from freestyle.types import (
     BinaryPredicate1D,
+    IntegrationType,
     Interface0DIterator,
     Nature,
     Noise,
     Interface0DIterator,
     Nature,
     Noise,
@@ -51,6 +52,8 @@ from freestyle.predicates import (
     ExternalContourUP1D,
     FalseBP1D,
     FalseUP1D,
     ExternalContourUP1D,
     FalseBP1D,
     FalseUP1D,
+    Length2DBP1D,
+    NotBP1D,
     NotUP1D,
     OrUP1D,
     QuantitativeInvisibilityUP1D,
     NotUP1D,
     OrUP1D,
     QuantitativeInvisibilityUP1D,
@@ -58,6 +61,7 @@ from freestyle.predicates import (
     TrueUP1D,
     WithinImageBoundaryUP1D,
     pyNatureUP1D,
     TrueUP1D,
     WithinImageBoundaryUP1D,
     pyNatureUP1D,
+    pyZBP1D,
     )
 from freestyle.shaders import (
     BackboneStretcherShader,
     )
 from freestyle.shaders import (
     BackboneStretcherShader,
@@ -1163,6 +1167,14 @@ class StrokeCleaner(StrokeShader):
         stroke.update_length()
 
 
         stroke.update_length()
 
 
+integration_types = {
+    'MEAN': IntegrationType.MEAN,
+    'MIN': IntegrationType.MIN,
+    'MAX': IntegrationType.MAX,
+    'FIRST': IntegrationType.FIRST,
+    'LAST': IntegrationType.LAST}
+
+
 # main function for parameter processing
 
 def process(layer_name, lineset_name):
 # main function for parameter processing
 
 def process(layer_name, lineset_name):
@@ -1291,6 +1303,16 @@ def process(layer_name, lineset_name):
         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))
         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)
+        if linestyle.sort_key == 'DISTANCE_FROM_CAMERA':
+            bpred = pyZBP1D(integration)
+        elif linestyle.sort_key == '2D_LENGTH':
+            bpred = Length2DBP1D()
+        if linestyle.sort_order == 'REVERSE':
+            bpred = NotBP1D(bpred)
+        Operators.sort(bpred)
     # prepare a list of stroke shaders
     shaders_list = []
     ###
     # prepare a list of stroke shaders
     shaders_list = []
     ###
index 197b0d2f9705a974778ee3b162b20b406e23299b..bedee24d8efd0006f45efbcaa425fea95ccd1999 100644 (file)
@@ -603,6 +603,18 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
             sub.active = linestyle.use_length_max
             sub.prop(linestyle, "length_max")
 
             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
+            row = col.row(align=True)
+            row.prop(linestyle, "sort_key", 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)
+
             ## Caps
             layout.label(text="Caps:")
             row = layout.row(align=True)
             ## Caps
             layout.label(text="Caps:")
             row = layout.row(align=True)
index 9a67284304cca8278a405bd82eb4808443a69bb5..e29aa142d76fe195b5abfbbfba739e86783374ed 100644 (file)
@@ -42,7 +42,7 @@ extern "C" {
  * and keep comment above the defines.
  * Use STRINGIFY() rather than defining with quotes */
 #define BLENDER_VERSION         270
  * and keep comment above the defines.
  * Use STRINGIFY() rather than defining with quotes */
 #define BLENDER_VERSION         270
-#define BLENDER_SUBVERSION      2
+#define BLENDER_SUBVERSION      3
 /* 262 was the last editmesh release but it has compatibility code for bmesh data */
 #define BLENDER_MINVERSION      262
 #define BLENDER_MINSUBVERSION   0
 /* 262 was the last editmesh release but it has compatibility code for bmesh data */
 #define BLENDER_MINVERSION      262
 #define BLENDER_MINSUBVERSION   0
index f826e611a114c61d542180b07fc1e8133d74abcc..78d062ce1f71dabcb42488b18dfb89aeda77264c 100644 (file)
@@ -81,7 +81,7 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle)
        linestyle->thickness = 3.0f;
        linestyle->thickness_position = LS_THICKNESS_CENTER;
        linestyle->thickness_ratio = 0.5f;
        linestyle->thickness = 3.0f;
        linestyle->thickness_position = LS_THICKNESS_CENTER;
        linestyle->thickness_ratio = 0.5f;
-       linestyle->flag = LS_SAME_OBJECT;
+       linestyle->flag = LS_SAME_OBJECT | LS_NO_SORTING;
        linestyle->chaining = LS_CHAINING_PLAIN;
        linestyle->rounds = 3;
        linestyle->min_angle = DEG2RADF(0.0f);
        linestyle->chaining = LS_CHAINING_PLAIN;
        linestyle->rounds = 3;
        linestyle->min_angle = DEG2RADF(0.0f);
@@ -89,6 +89,8 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle)
        linestyle->min_length = 0.0f;
        linestyle->max_length = 10000.0f;
        linestyle->split_length = 100;
        linestyle->min_length = 0.0f;
        linestyle->max_length = 10000.0f;
        linestyle->split_length = 100;
+       linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA;
+       linestyle->integration_type = LS_INTEGRATION_MEAN;
 
        BLI_listbase_clear(&linestyle->color_modifiers);
        BLI_listbase_clear(&linestyle->alpha_modifiers);
 
        BLI_listbase_clear(&linestyle->color_modifiers);
        BLI_listbase_clear(&linestyle->alpha_modifiers);
index 2dd227ef036d28e26ee041d37c8dd9636b206c24..41b95064ac6acf30aa511473a3c04b11c8f5055d 100644 (file)
@@ -43,6 +43,7 @@
 #include "DNA_mesh_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_sdna_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_sdna_types.h"
+#include "DNA_linestyle_types.h"
 
 #include "DNA_genfile.h"
 
 
 #include "DNA_genfile.h"
 
@@ -171,4 +172,14 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
                        me->smoothresh = DEG2RADF(me->smoothresh);
                }
        }
                        me->smoothresh = DEG2RADF(me->smoothresh);
                }
        }
+
+       if (!MAIN_VERSION_ATLEAST(main, 270, 3)) {
+               FreestyleLineStyle *linestyle;
+
+               for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
+                       linestyle->flag |= LS_NO_SORTING;
+                       linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA;
+                       linestyle->integration_type = LS_INTEGRATION_MEAN;
+               }
+       }
 }
 }
index d6caf16f7aa00ad7fdf3e74501e0e0f528679079..b455ef016b28b5eb364e2cd100a9d63f53e028ea 100644 (file)
@@ -59,8 +59,11 @@ void BLO_update_defaults_startup_blend(Main *main)
                }
        }
 
                }
        }
 
-       for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next)
-               linestyle->flag = LS_SAME_OBJECT;
+       for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
+               linestyle->flag = LS_SAME_OBJECT | LS_NO_SORTING;
+               linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA;
+               linestyle->integration_type = LS_INTEGRATION_MEAN;
+       }
 
        {
                bScreen *screen;
 
        {
                bScreen *screen;
index 19c4e057a96d5e856b5e80c27f6849cf8836d987..8d5f81ede5a83485c5d658ba09bb2f562b8429ca 100644 (file)
@@ -368,6 +368,8 @@ typedef struct LineStyleThicknessModifier_Calligraphy {
 #define LS_MAX_2D_ANGLE       (1 <<  8)
 #define LS_SPLIT_LENGTH       (1 <<  9)
 #define LS_SPLIT_PATTERN      (1 << 10)
 #define LS_MAX_2D_ANGLE       (1 <<  8)
 #define LS_SPLIT_LENGTH       (1 <<  9)
 #define LS_SPLIT_PATTERN      (1 << 10)
+#define LS_NO_SORTING         (1 << 11)
+#define LS_REVERSE_ORDER      (1 << 12)  /* for sorting */
 
 /* FreestyleLineStyle::chaining */
 #define LS_CHAINING_PLAIN    1
 
 /* FreestyleLineStyle::chaining */
 #define LS_CHAINING_PLAIN    1
@@ -384,6 +386,17 @@ typedef struct LineStyleThicknessModifier_Calligraphy {
 #define LS_THICKNESS_OUTSIDE   3
 #define LS_THICKNESS_RELATIVE  4 /* thickness_ratio is used */
 
 #define LS_THICKNESS_OUTSIDE   3
 #define LS_THICKNESS_RELATIVE  4 /* thickness_ratio is used */
 
+/* FreestyleLineStyle::sort_key */
+#define LS_SORT_KEY_DISTANCE_FROM_CAMERA  1
+#define LS_SORT_KEY_2D_LENGTH             2
+
+/* FreestyleLineStyle::integration_type */
+#define LS_INTEGRATION_MEAN   1
+#define LS_INTEGRATION_MIN    2
+#define LS_INTEGRATION_MAX    3
+#define LS_INTEGRATION_FIRST  4
+#define LS_INTEGRATION_LAST   5
+
 typedef struct FreestyleLineStyle {
        ID id;
        struct AnimData *adt;
 typedef struct FreestyleLineStyle {
        ID id;
        struct AnimData *adt;
@@ -401,6 +414,7 @@ typedef struct FreestyleLineStyle {
        unsigned short split_dash1, split_gap1;
        unsigned short split_dash2, split_gap2;
        unsigned short split_dash3, split_gap3;
        unsigned short split_dash1, split_gap1;
        unsigned short split_dash2, split_gap2;
        unsigned short split_dash3, split_gap3;
+       int sort_key, integration_type;
        int pad;
        unsigned short dash1, gap1, dash2, gap2, dash3, gap3;
        int panel; /* for UI */
        int pad;
        unsigned short dash1, gap1, dash2, gap2, dash3, gap3;
        int panel; /* for UI */
index 0619bb0352adbed95267408c954e7e066cc72394..e97f3c2b4188bb8643912ded7da64c0a918cfd0c 100644 (file)
@@ -915,6 +915,24 @@ static void rna_def_linestyle(BlenderRNA *brna)
                {LS_THICKNESS_RELATIVE, "RELATIVE", 0, "Relative", "Stroke thickness is split by a user-defined ratio"},
                {0, NULL, 0, NULL, NULL}
        };
                {LS_THICKNESS_RELATIVE, "RELATIVE", 0, "Relative", "Stroke thickness is split by a user-defined ratio"},
                {0, NULL, 0, NULL, NULL}
        };
+       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)"},
+               {0, NULL, 0, NULL, NULL}
+       };
+       static EnumPropertyItem sort_order_items[] = {
+               {0, "DEFAULT", 0, "Default", "Default order of the sort key"},
+               {LS_REVERSE_ORDER, "REVERSE", 0, "Reverse", "Reverse order"},
+               {0, NULL, 0, NULL, NULL}
+       };
+       static EnumPropertyItem integration_type_items[] = {
+               {LS_INTEGRATION_MEAN, "MEAN", 0, "Mean", "The value computed for the chain is the mean of the values obtained for chain vertices"},
+               {LS_INTEGRATION_MIN, "MIN", 0, "Min", "The value computed for the chain is the minimum of the values obtained for chain vertices"},
+               {LS_INTEGRATION_MAX, "MAX", 0, "Max", "The value computed for the chain is the maximum of the values obtained for chain vertices"},
+               {LS_INTEGRATION_FIRST, "FIRST", 0, "First", "The value computed for the chain is the value obtained for the first chain vertex"},
+               {LS_INTEGRATION_LAST, "LAST", 0, "Last", "The value computed for the chain is the value obtained for the last chain vertex"},
+               {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");
 
        srna = RNA_def_struct(brna, "FreestyleLineStyle", "ID");
        RNA_def_struct_ui_text(srna, "Freestyle Line Style", "Freestyle line style, reusable by multiple line sets");
@@ -1104,6 +1122,29 @@ static void rna_def_linestyle(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Material Boundary", "If true, chains of feature edges are split at material boundaries");
        RNA_def_property_update(prop, NC_LINESTYLE, NULL);
 
        RNA_def_property_ui_text(prop, "Material Boundary", "If true, chains of feature edges are split at material boundaries");
        RNA_def_property_update(prop, NC_LINESTYLE, NULL);
 
+       prop = RNA_def_property(srna, "use_sorting", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", LS_NO_SORTING);
+       RNA_def_property_ui_text(prop, "Sorting", "Arrange the stacking order of strokes");
+       RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+       prop = RNA_def_property(srna, "sort_key", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "sort_key");
+       RNA_def_property_enum_items(prop, sort_key_items);
+       RNA_def_property_ui_text(prop, "Sort Key", "Select the sort key to determine the stacking order of chains");
+       RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+       prop = RNA_def_property(srna, "sort_order", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
+       RNA_def_property_enum_items(prop, sort_order_items);
+       RNA_def_property_ui_text(prop, "Sort Order", "Select the sort order");
+       RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+       prop = RNA_def_property(srna, "integration_type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "integration_type");
+       RNA_def_property_enum_items(prop, integration_type_items);
+       RNA_def_property_ui_text(prop, "Integration Type", "Select the way how the sort key is computed for each chain");
+       RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
        prop = RNA_def_property(srna, "use_dashed_line", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_DASHED_LINE);
        RNA_def_property_ui_text(prop, "Dashed Line", "Enable or disable dashed line");
        prop = RNA_def_property(srna, "use_dashed_line", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_DASHED_LINE);
        RNA_def_property_ui_text(prop, "Dashed Line", "Enable or disable dashed line");