mask object blending and alpha options
authorCampbell Barton <ideasman42@gmail.com>
Thu, 31 May 2012 12:12:28 +0000 (12:12 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 31 May 2012 12:12:28 +0000 (12:12 +0000)
release/scripts/startup/bl_ui/space_clip.py
source/blender/blenkernel/intern/mask.c
source/blender/editors/interface/interface_templates.c
source/blender/makesdna/DNA_mask_types.h
source/blender/makesrna/intern/rna_mask.c

index 6815aef56d600866ee4dfabcc71cc4e260ea495b..a5b1996ae0de097d8651b7f9d97efa11db6194e4 100644 (file)
@@ -591,6 +591,13 @@ class CLIP_PT_mask_objects(Panel):
         active = mask.objects.active
         if active:
             layout.prop(active, "name")
+            
+            # blending
+            row = layout.row(align=True)
+            row.prop(active, "alpha")
+            row.prop(active, "invert", text="", icon='IMAGE_ALPHA')
+
+            layout.prop(active, "blend")
 
 
 class CLIP_PT_active_mask_spline(Panel):
index 34396544b770c2a59e12e9c52862cc7ea93e9a14..42a083e56d7f751306a114b700ecaf5b89152026 100644 (file)
@@ -1729,13 +1729,57 @@ void BKE_mask_object_shape_changed_remove(MaskObject *maskobj, int index, int co
        }
 }
 
+/* local functions */
+static void invert_vn_vn(float *array, const int size)
+{
+       float *arr = array + (size - 1);
+       int i = size;
+       while (i--) {
+               *(arr) = 1.0f - *(arr);
+               arr--;
+       }
+}
+
+static void m_invert_vn_vn(float *array, const float f, const int size)
+{
+       float *arr = array + (size - 1);
+       int i = size;
+       while (i--) {
+               *(arr) = 1.0f - (*(arr) * f);
+               arr--;
+       }
+}
+
+static void clamp_vn_vn(float *array, const int size)
+{
+       float *arr = array + (size - 1);
+
+       int i = size;
+       while (i--) {
+               if      (*arr < 0.0f) *arr = 0.0f;
+               else if (*arr > 1.0f) *arr = 1.0f;
+               arr--;
+       }
+}
+
 /* rasterization */
 void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer)
 {
        MaskObject *maskobj;
 
+       /* temp blending buffer */
+       const int buffer_size = width * height;
+       float *buffer_tmp = MEM_mallocN(sizeof(float) * buffer_size, __func__);
+
        for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) {
                MaskSpline *spline;
+               float alpha;
+
+               if (maskobj->restrictflag & MASK_RESTRICT_RENDER) {
+                       continue;
+               }
+
+               memset(buffer_tmp, 0, sizeof(float) * buffer_size);
 
                for (spline = maskobj->splines.first; spline; spline = spline->next) {
                        float (*diff_points)[2];
@@ -1774,17 +1818,67 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer)
                        }
 
                        if (tot_diff_point) {
-                               PLX_raskterize((float (*)[2])diff_points, tot_diff_point, buffer, width, height);
+                               PLX_raskterize((float (*)[2])diff_points, tot_diff_point,
+                                              buffer_tmp, width, height);
 
                                if (tot_diff_feather_points) {
                                        PLX_raskterize_feather((float (*)[2])diff_points, tot_diff_point,
                                                               (float (*)[2])diff_feather_points, tot_diff_feather_points,
-                                                              buffer, width, height);
+                                                              buffer_tmp, width, height);
+                               }
+
+                               if (tot_diff_point) {
+                                       MEM_freeN(diff_points);
+                               }
+                               if (tot_diff_feather_points) {
                                        MEM_freeN(diff_feather_points);
                                }
+                       }
+               }
+
+               /* blend with original */
+               if (maskobj->blend_flag & MASK_BLENDFLAG_INVERT) {
+                       /* apply alpha multiply before inverting */
+                       if (maskobj->alpha != 1.0f) {
+                               m_invert_vn_vn(buffer_tmp, maskobj->alpha, buffer_size);
+                       }
+                       else {
+                               invert_vn_vn(buffer_tmp, buffer_size);
+                       }
 
-                               MEM_freeN(diff_points);
+                       alpha = 1.0f;
+               }
+               else {
+                       alpha = maskobj->alpha;
+               }
+
+               switch (maskobj->blend) {
+                       case MASK_BLEND_SUBTRACT:
+                       {
+                               if (alpha == 1.0f) {
+                                       sub_vn_vn(buffer, buffer_tmp, buffer_size);
+                               }
+                               else {
+                                       msub_vn_vn(buffer, buffer_tmp, alpha, buffer_size);
+                               }
+                               break;
+                       }
+                       case MASK_BLEND_ADD:
+                       default:
+                       {
+                               if (alpha == 1.0f) {
+                                       add_vn_vn(buffer, buffer_tmp, buffer_size);
+                               }
+                               else {
+                                       madd_vn_vn(buffer, buffer_tmp, alpha, buffer_size);
+                               }
+                               break;
                        }
                }
+
+               /* clamp at the end */
+               clamp_vn_vn(buffer, buffer_size);
        }
+
+       MEM_freeN(buffer_tmp);
 }
index 1acfefe8a4c4fd43718c44658037700847fbfbcf..d23cd88cf0577fc9d8f30ac597a985b99116fe5a 100644 (file)
@@ -2251,6 +2251,7 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe
                // uiItemR(row, itemptr, "alpha", 0, "", ICON_NONE); // enable when used
                uiItemR(row, itemptr, "hide", 0, "", 0);
                uiItemR(row, itemptr, "hide_select", 0, "", 0);
+               uiItemR(row, itemptr, "hide_render", 0, "", 0);
 
                uiBlockSetEmboss(block, UI_EMBOSS);
        }
index d427e1561cb38c4a1c1845e4c5b3a1845feb4910..d677239e300f81ef32b26750134204bf94c4cba8 100644 (file)
@@ -108,10 +108,14 @@ typedef struct MaskObject {
        struct MaskSpline *act_spline;     /* active spline */
        struct MaskSplinePoint *act_point; /* active point */
 
+       /* blending options */
        float  alpha;
+       char   blend;
+       char   blend_flag;
+
        //char   flag;             /* not used yet */
        char   restrictflag;     /* matching 'Object' flag of the same name - eventually use in the outliner  */
-       char   pad[3];
+       char   pad[1];
 } MaskObject;
 
 /* MaskParent->flag */
@@ -144,4 +148,16 @@ enum {
        MASK_DT_WHITE
 };
 
+/* maskobj->blend */
+enum {
+       MASK_BLEND_ADD      = 0,
+       MASK_BLEND_SUBTRACT = 1
+};
+
+/* maskobj->blend_flag */
+enum {
+       MASK_BLENDFLAG_INVERT = (1 << 0)
+};
+
+
 #endif // __DNA_MASK_TYPES_H__
index 393ca5f32446cb67cb111f1496ca79b5dd45f8cf..c072676b665353b9a7db70472696433d2439984a 100644 (file)
@@ -126,6 +126,11 @@ static void rna_Mask_object_active_index_range(PointerRNA *ptr, int *min, int *m
        *softmax = *max;
 }
 
+static char *rna_MaskObject_path(PointerRNA *ptr)
+{
+       return BLI_sprintfN("objects[\"%s\"]", ((MaskObject *)ptr->data)->name);
+}
+
 static PointerRNA rna_Mask_object_active_get(PointerRNA *ptr)
 {
        Mask *mask = (Mask *)ptr->id.data;
@@ -483,7 +488,8 @@ static void rna_def_maskSpline(BlenderRNA *brna)
        static EnumPropertyItem spline_interpolation_items[] = {
                {MASK_SPLINE_INTERP_LINEAR, "LINEAR", 0, "Linear", ""},
                {MASK_SPLINE_INTERP_EASE, "EASE", 0, "Ease", ""},
-               {0, NULL, 0, NULL, NULL}};
+               {0, NULL, 0, NULL, NULL}
+       };
 
        StructRNA *srna;
        PropertyRNA *prop;
@@ -510,6 +516,12 @@ static void rna_def_maskSpline(BlenderRNA *brna)
 
 static void rna_def_mask_object(BlenderRNA *brna)
 {
+       static EnumPropertyItem maskobj_blend_mode_items[] = {
+               {MASK_BLEND_ADD, "ADD", 0, "Add", ""},
+               {MASK_BLEND_SUBTRACT, "SUBTRACT", 0, "Subtract", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
+
        StructRNA *srna;
        PropertyRNA *prop;
 
@@ -518,6 +530,7 @@ static void rna_def_mask_object(BlenderRNA *brna)
 
        srna = RNA_def_struct(brna, "MaskObject", NULL);
        RNA_def_struct_ui_text(srna, "Mask Object", "Single object used for masking pixels");
+       RNA_def_struct_path_func(srna, "rna_MaskObject_path");
 
        /* name */
        prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
@@ -551,14 +564,28 @@ static void rna_def_mask_object(BlenderRNA *brna)
        RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_RENDER);
        RNA_def_property_ui_text(prop, "Restrict Render", "Restrict renderability");
        RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
-       RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL);
+       RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL);
 
        /* render settings */
        prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "alpha");
        RNA_def_property_range(prop, 0.0, 1.0f);
        RNA_def_property_ui_text(prop, "Opacity", "Render Opacity");
-       RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL);
+       RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL);
+
+       /* weight interpolation */
+       prop = RNA_def_property(srna, "blend", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "blend");
+       RNA_def_property_enum_items(prop, maskobj_blend_mode_items);
+       RNA_def_property_ui_text(prop, "Blend", "Method of blending mask objects");
+       RNA_def_property_update(prop, 0, "rna_Mask_update_data");
+       RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL);
+
+       prop = RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MASK_BLENDFLAG_INVERT);
+       RNA_def_property_ui_text(prop, "Restrict View", "Restrict visibility in the viewport");
+       RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL);
+
 }
 
 static void rna_def_maskobjects(BlenderRNA *brna, PropertyRNA *cprop)
@@ -616,6 +643,9 @@ static void rna_def_mask(BlenderRNA *brna)
        RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_int_funcs(prop, "rna_Mask_object_active_index_get", "rna_Mask_object_active_index_set", "rna_Mask_object_active_index_range");
        RNA_def_property_ui_text(prop, "Active Shape Index", "Index of active object in list of all mask's objects");
+
+       /* pointers */
+       rna_def_animdata_common(srna);
 }
 
 void RNA_def_mask(BlenderRNA *brna)