[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [57305] branches/soc-2011-tomato: Experimental operator to cleanup mask shapekeys

Sergey Sharybin sergey.vfx at gmail.com
Sun Jun 9 12:04:25 CEST 2013


Revision: 57305
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=57305
Author:   nazgul
Date:     2013-06-09 10:04:25 +0000 (Sun, 09 Jun 2013)
Log Message:
-----------
Experimental operator to cleanup mask shapekeys

For every shapekey operator check whether mask shape
stays within given tolerance and if so, shapekey is
removing.

TODO:
- Radius and weight are not handled completely crorrect,
  need some smarter way to handle them.
- There're huge issues with depsgraph tag update for
  mask and acutal mask update -- worked around by manual
  call of BKE_mask_evaluate from places where shapekeys
  are removing.

  Would need to look further into this in trunk.

Modified Paths:
--------------
    branches/soc-2011-tomato/release/scripts/startup/bl_ui/properties_mask_common.py
    branches/soc-2011-tomato/source/blender/editors/mask/mask_edit.c
    branches/soc-2011-tomato/source/blender/editors/mask/mask_intern.h
    branches/soc-2011-tomato/source/blender/editors/mask/mask_shapekey.c

Modified: branches/soc-2011-tomato/release/scripts/startup/bl_ui/properties_mask_common.py
===================================================================
--- branches/soc-2011-tomato/release/scripts/startup/bl_ui/properties_mask_common.py	2013-06-09 09:51:19 UTC (rev 57304)
+++ branches/soc-2011-tomato/release/scripts/startup/bl_ui/properties_mask_common.py	2013-06-09 10:04:25 UTC (rev 57305)
@@ -262,6 +262,7 @@
         col.operator("mask.shape_key_insert")
         col.operator("mask.shape_key_feather_reset")
         col.operator("mask.shape_key_rekey")
+        col.operator("mask.shape_key_cleanup")
 
 
 class MASK_MT_mask(Menu):
@@ -324,6 +325,7 @@
         layout.operator("mask.shape_key_insert")
         layout.operator("mask.shape_key_feather_reset")
         layout.operator("mask.shape_key_rekey")
+        layout.operator("mask.shape_key_cleanup")
 
 
 class MASK_MT_select(Menu):

Modified: branches/soc-2011-tomato/source/blender/editors/mask/mask_edit.c
===================================================================
--- branches/soc-2011-tomato/source/blender/editors/mask/mask_edit.c	2013-06-09 09:51:19 UTC (rev 57304)
+++ branches/soc-2011-tomato/source/blender/editors/mask/mask_edit.c	2013-06-09 10:04:25 UTC (rev 57305)
@@ -412,6 +412,7 @@
 	WM_operatortype_append(MASK_OT_shape_key_clear);
 	WM_operatortype_append(MASK_OT_shape_key_feather_reset);
 	WM_operatortype_append(MASK_OT_shape_key_rekey);
+	WM_operatortype_append(MASK_OT_shape_key_cleanup);
 
 	/* layers */
 	WM_operatortype_append(MASK_OT_layer_move);

Modified: branches/soc-2011-tomato/source/blender/editors/mask/mask_intern.h
===================================================================
--- branches/soc-2011-tomato/source/blender/editors/mask/mask_intern.h	2013-06-09 09:51:19 UTC (rev 57304)
+++ branches/soc-2011-tomato/source/blender/editors/mask/mask_intern.h	2013-06-09 10:04:25 UTC (rev 57305)
@@ -107,5 +107,6 @@
 void MASK_OT_shape_key_clear(struct wmOperatorType *ot);
 void MASK_OT_shape_key_feather_reset(struct wmOperatorType *ot);
 void MASK_OT_shape_key_rekey(struct wmOperatorType *ot);
+void MASK_OT_shape_key_cleanup(struct wmOperatorType *ot);
 
 #endif /* __MASK_INTERN_H__ */

Modified: branches/soc-2011-tomato/source/blender/editors/mask/mask_shapekey.c
===================================================================
--- branches/soc-2011-tomato/source/blender/editors/mask/mask_shapekey.c	2013-06-09 09:51:19 UTC (rev 57304)
+++ branches/soc-2011-tomato/source/blender/editors/mask/mask_shapekey.c	2013-06-09 10:04:25 UTC (rev 57305)
@@ -38,6 +38,7 @@
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
 #include "BKE_mask.h"
+#include "BKE_report.h"
 
 #include "DNA_object_types.h"
 #include "DNA_mask_types.h"
@@ -123,6 +124,9 @@
 	}
 
 	if (change) {
+		Scene *scene = CTX_data_scene(C);
+		BKE_mask_evaluate(mask, CFRA, TRUE);
+
 		WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
 		DAG_id_tag_update(&mask->id, 0);
 
@@ -450,3 +454,114 @@
 
 	return change;
 }
+
+/******************** shape key cleanup operator *********************/
+
+static int mask_shape_key_cleanup_exec(bContext *C, wmOperator *op)
+{
+	Mask *mask = CTX_data_edit_mask(C);
+	MaskLayer *mask_layer = BKE_mask_layer_active(mask);
+	MaskLayerShape *current_shape, *next_shape;
+	int removed_count = 0;
+	const float tolerance = RNA_float_get(op->ptr, "tolerance");
+	const float tolerance_squared = tolerance * tolerance;
+	int width, height;
+	float side;
+
+	if (mask_layer == NULL) {
+		return OPERATOR_CANCELLED;
+	}
+
+	ED_mask_get_size(CTX_wm_area(C), &width, &height);
+	side = max_ff(width, height);
+
+	for (current_shape = mask_layer->splines_shapes.first;
+	     current_shape;
+	     current_shape = next_shape)
+	{
+		MaskLayerShape *previous_shape = current_shape->prev;
+		MaskLayerShapeElem *previous_elements, *current_elements, *next_elements;
+		int i;
+		float interpolation_factor, inv_interpolation_factor;
+		float average_error;
+
+		next_shape = current_shape->next;
+
+		if (previous_shape == NULL || next_shape == NULL) {
+			continue;
+		}
+
+		previous_elements = (MaskLayerShapeElem *) previous_shape->data;
+		current_elements = (MaskLayerShapeElem *) current_shape->data;
+		next_elements = (MaskLayerShapeElem *) next_shape->data;
+
+		if (previous_shape->tot_vert != current_shape->tot_vert ||
+		    previous_shape->tot_vert != next_shape->tot_vert ||
+		    current_shape->tot_vert != next_shape->tot_vert)
+		{
+			printf("%s: unexpected mistmatch between shapes vertices number.\n", __func__);
+			continue;
+		}
+
+		interpolation_factor = (float)(current_shape->frame - previous_shape->frame) /
+		                       (float)(next_shape->frame - previous_shape->frame);
+		inv_interpolation_factor = 1.0f - interpolation_factor;
+
+		average_error = 0.0f;
+		for (i = 0; i < current_shape->tot_vert; i++) {
+			int j;
+			for (j = 0; j < MASK_OBJECT_SHAPE_ELEM_SIZE; j++) {
+				float interpolated_value;
+				float current_error;
+				interpolated_value = inv_interpolation_factor * previous_elements[i].value[j] +
+				                     interpolation_factor * next_elements[i].value[j];
+				current_error = (current_elements[i].value[j] - interpolated_value) * side;
+				average_error += current_error * current_error;
+			}
+		}
+		average_error /= (float) current_shape->tot_vert;
+
+		if (ELEM(current_shape->frame, 3, 9)) {
+			printf("%d %f\n", current_shape->frame, average_error);
+		}
+
+		if (average_error < tolerance_squared) {
+			BLI_remlink(&mask_layer->splines_shapes, current_shape);
+			BKE_mask_layer_shape_free(current_shape);
+			removed_count++;
+		}
+	}
+
+	if (removed_count > 0) {
+		Scene *scene = CTX_data_scene(C);
+		BKE_mask_evaluate(mask, CFRA, TRUE);
+
+		WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
+		DAG_id_tag_update(&mask->id, 0);
+	}
+
+	BKE_reportf(op->reports, RPT_INFO, "Removed %d keys", removed_count);
+
+	return OPERATOR_FINISHED;
+}
+
+void MASK_OT_shape_key_cleanup(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Cleanup Shape Keys";
+	ot->description = "Remove keyframes which doesn't have much affect on mask shape";
+	ot->idname = "MASK_OT_shape_key_cleanup";
+
+	/* api callbacks */
+	ot->exec = mask_shape_key_cleanup_exec;
+	ot->poll = ED_maskedit_mask_poll;
+
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+	/* properties */
+	RNA_def_float(ot->srna, "tolerance", 0.8f, -FLT_MAX, FLT_MAX,
+	              "Tolerance", "Average distance in pixels which mask is allowed to "
+	                           "slide off after removing shapekey",
+	              -100.0f, 100.0f);
+}




More information about the Bf-blender-cvs mailing list