[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [46695] trunk/blender/source/blender/ editors: modal operation for bevel and inset:

Antony Riakiotakis kalast at gmail.com
Wed May 16 16:30:41 CEST 2012


Revision: 46695
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=46695
Author:   psy-fi
Date:     2012-05-16 14:30:41 +0000 (Wed, 16 May 2012)
Log Message:
-----------
modal operation for bevel and inset:

This commit adds some first building blocks for the two operators to work modally based on mouse input. To make their function easier, two hotkeys are introduced, Ctrl+B for bevel and I for inset.

TODO:
After discussion with Campbell, we would like to add scale-style line indicators for the operators. This is already done for transform operators but a new interface for mesh operations may have to be written using pieces from that code since, strictly speaking bevel and inset are not exactly "transform" operators.

Also, a better input method for inset is needed and more options exposed. The method implemented right now uses mouse move for thickness and ctrl-mouse move for depth. These are calculated using the distance of the selection center in screen space and the mouse position. While that may work and prevents abrupt changes in values when switching from thickness tweak mode to depth tweak mode, it limits the magnitude of values that can be put into the tool especially in small or large scale. 

Alternatives until a better method is written include:

* use relative offset (works but may give strange results)
* tweak manually after the operation.

Modified Paths:
--------------
    trunk/blender/source/blender/editors/include/ED_mesh.h
    trunk/blender/source/blender/editors/include/ED_transform.h
    trunk/blender/source/blender/editors/mesh/editmesh_tools.c
    trunk/blender/source/blender/editors/mesh/editmesh_utils.c
    trunk/blender/source/blender/editors/mesh/mesh_ops.c
    trunk/blender/source/blender/editors/space_view3d/view3d_edit.c
    trunk/blender/source/blender/editors/transform/transform.c

Modified: trunk/blender/source/blender/editors/include/ED_mesh.h
===================================================================
--- trunk/blender/source/blender/editors/include/ED_mesh.h	2012-05-16 14:25:25 UTC (rev 46694)
+++ trunk/blender/source/blender/editors/include/ED_mesh.h	2012-05-16 14:30:41 UTC (rev 46695)
@@ -267,6 +267,18 @@
                            const short skip_em_vert_array_init);
 void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
 
+/* mesh backup */
+typedef struct BMBackup {
+	struct BMesh *bmcopy;
+} BMBackup;
+
+/* save a copy of the bmesh for restoring later */
+struct BMBackup EDBM_redo_state_store(struct BMEditMesh *em);
+/* restore a bmesh from backup */
+void EDBM_redo_state_restore(struct BMBackup, struct BMEditMesh *em, int recalctess);
+/* delete the backup, optionally flushing it to an editmesh */
+void EDBM_redo_state_free(struct BMBackup *, struct BMEditMesh *em, int recalctess);
+
 #ifdef __cplusplus
 }
 #endif

Modified: trunk/blender/source/blender/editors/include/ED_transform.h
===================================================================
--- trunk/blender/source/blender/editors/include/ED_transform.h	2012-05-16 14:25:25 UTC (rev 46694)
+++ trunk/blender/source/blender/editors/include/ED_transform.h	2012-05-16 14:30:41 UTC (rev 46695)
@@ -100,7 +100,7 @@
  * returns 1 if successful, 0 otherwise (usually means there's no selection)
  * (if 0 is returns, *vec is unmodified)
  * */
-int calculateTransformCenter(struct bContext *C, int centerMode, float *vec);
+int calculateTransformCenter(struct bContext *C, int centerMode, float *cent3d, int *cent2d);
 
 struct TransInfo;
 struct ScrArea;

Modified: trunk/blender/source/blender/editors/mesh/editmesh_tools.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/editmesh_tools.c	2012-05-16 14:25:25 UTC (rev 46694)
+++ trunk/blender/source/blender/editors/mesh/editmesh_tools.c	2012-05-16 14:30:41 UTC (rev 46695)
@@ -4308,21 +4308,79 @@
 	RNA_def_float(ot->srna, "factor", 0.1f, -FLT_MAX, FLT_MAX, "Factor", "", 0.0f, 1.0f);
 }
 
-/* bevel! yay!!*/
-static int edbm_bevel_exec(bContext *C, wmOperator *op)
+typedef struct {
+	BMEditMesh *em;
+	BMBackup mesh_backup;
+	float *weights;
+	int li;
+	int mcenter[2];
+	float initial_length;
+	int is_modal;
+} BevelData;
+
+#define HEADER_LENGTH 180
+
+static void edbm_bevel_update_header(wmOperator *op, bContext *C)
 {
+	static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RClick), factor: %f, , Use Dist (D): %s: Use Even (E): %s";
+
+	char msg[HEADER_LENGTH];
+	ScrArea *sa = CTX_wm_area(C);
+
+	if (sa) {
+		BLI_snprintf(msg, HEADER_LENGTH, str,
+		             RNA_float_get(op->ptr, "percent"),
+		             RNA_boolean_get(op->ptr, "use_dist") ? "On" : "Off",
+		             RNA_boolean_get(op->ptr, "use_even") ? "On" : "Off"
+		             );
+
+		ED_area_headerprint(sa, msg);
+	}
+}
+
+static void edbm_bevel_recalc_weights(wmOperator *op)
+{
+	float df, s, ftot;
+	int i;
+	int recursion = 1; /* RNA_int_get(op->ptr, "recursion"); */ /* temp removed, see comment below */
+	BevelData *opdata = op->customdata;
+
+	if (opdata->weights) {
+		/* TODO should change to free only when new recursion is greater than old */
+		MEM_freeN(opdata->weights);
+	}
+	opdata->weights = MEM_mallocN(sizeof(float) * recursion, "bevel weights");
+
+	/* ugh, stupid math depends somewhat on angles!*/
+	/* dfac = 1.0/(float)(recursion + 1); */ /* UNUSED */
+	df = 1.0;
+	for (i = 0, ftot = 0.0f; i < recursion; i++) {
+		s = powf(df, 1.25f);
+
+		opdata->weights[i] = s;
+		ftot += s;
+
+		df *= 2.0f;
+	}
+
+	mul_vn_fl(opdata->weights, recursion, 1.0f / (float)ftot);
+}
+
+static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal)
+{
 	Object *obedit = CTX_data_edit_object(C);
 	BMEditMesh *em = BMEdit_FromObject(obedit);
 	BMIter iter;
 	BMEdge *eed;
-	BMOperator bmop;
-	float factor = RNA_float_get(op->ptr, "percent") /*, dfac */ /* UNUSED */, df, s;
-	int i, recursion = 1; /* RNA_int_get(op->ptr, "recursion"); */ /* temp removed, see comment below */
-	const int use_even = RNA_boolean_get(op->ptr, "use_even");
-	const int use_dist = RNA_boolean_get(op->ptr, "use_dist");
-	float *w = NULL, ftot;
+	BevelData *opdata;
 	int li;
 	
+	if (em == NULL) {
+		return 0;
+	}
+
+	op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator");
+
 	BM_data_layer_add(em->bm, &em->bm->edata, CD_PROP_FLT);
 	li = CustomData_number_of_layers(&em->bm->edata, CD_PROP_FLT) - 1;
 	
@@ -4333,52 +4391,201 @@
 		*dv = d;
 	}
 	
-	if (em == NULL) {
-		return OPERATOR_CANCELLED;
-	}
+	opdata->em = em;
+	opdata->li = li;
+	opdata->weights = NULL;
+	opdata->is_modal = is_modal;
 	
-	w = MEM_mallocN(sizeof(float) * recursion, "bevel weights");
+	/* avoid the cost of allocating a bm copy */
+	if (is_modal)
+		opdata->mesh_backup = EDBM_redo_state_store(em);
+	edbm_bevel_recalc_weights(op);
 
-	/* ugh, stupid math depends somewhat on angles!*/
-	/* dfac = 1.0/(float)(recursion + 1); */ /* UNUSED */
-	df = 1.0;
-	for (i = 0, ftot = 0.0f; i < recursion; i++) {
-		s = powf(df, 1.25f);
+	return 1;
+}
 
-		w[i] = s;
-		ftot += s;
+static int edbm_bevel_calc(bContext *C, wmOperator *op)
+{
+	BevelData *opdata = op->customdata;
+	BMEditMesh *em = opdata->em;
+	BMOperator bmop;
+	int i;
 
-		df *= 2.0f;
+	float factor = RNA_float_get(op->ptr, "percent") /*, dfac */ /* UNUSED */;
+	int recursion = 1; /* RNA_int_get(op->ptr, "recursion"); */ /* temp removed, see comment below */
+	const int use_even = RNA_boolean_get(op->ptr, "use_even");
+	const int use_dist = RNA_boolean_get(op->ptr, "use_dist");
+
+	/* revert to original mesh */
+	if (opdata->is_modal) {
+		EDBM_redo_state_restore(opdata->mesh_backup, em, FALSE);
 	}
 
-	mul_vn_fl(w, recursion, 1.0f / (float)ftot);
-
 	for (i = 0; i < recursion; i++) {
-		float fac = w[recursion - i - 1] * factor;
+		float fac = opdata->weights[recursion - i - 1] * factor;
 
+
 		if (!EDBM_op_init(em, &bmop, op,
 		                  "bevel geom=%hev percent=%f lengthlayer=%i use_lengths=%b use_even=%b use_dist=%b",
-		                  BM_ELEM_SELECT, fac, li, TRUE, use_even, use_dist))
+		                  BM_ELEM_SELECT, fac, opdata->li, TRUE, use_even, use_dist))
 		{
-			return OPERATOR_CANCELLED;
+			return 0;
 		}
 		
 		BMO_op_exec(em->bm, &bmop);
 		if (!EDBM_op_finish(em, &bmop, op, TRUE))
-			return OPERATOR_CANCELLED;
+			return 0;
 	}
 	
-	BM_data_layer_free_n(em->bm, &em->bm->edata, CD_PROP_FLT, li);
+	EDBM_mesh_normals_update(opdata->em);
 	
-	MEM_freeN(w);
+	EDBM_update_generic(C, opdata->em, TRUE);
 
-	EDBM_mesh_normals_update(em);
+	return 1;
+}
 
-	EDBM_update_generic(C, em, TRUE);
+static void edbm_bevel_exit(bContext *C, wmOperator *op)
+{
+	BevelData *opdata = op->customdata;
 
+	ScrArea *sa = CTX_wm_area(C);
+
+	if (sa) {
+		ED_area_headerprint(sa, NULL);
+	}
+	BM_data_layer_free_n(opdata->em->bm, &opdata->em->bm->edata, CD_PROP_FLT, opdata->li);
+
+	if (opdata->weights)
+		MEM_freeN(opdata->weights);
+	if (opdata->is_modal) {
+		EDBM_redo_state_free(&opdata->mesh_backup, NULL, FALSE);
+	}
+	MEM_freeN(opdata);
+	op->customdata = NULL;
+}
+
+static int edbm_bevel_cancel(bContext *C, wmOperator *op)
+{
+	BevelData *opdata = op->customdata;
+	if (opdata->is_modal) {
+		EDBM_redo_state_free(&opdata->mesh_backup, opdata->em, TRUE);
+		EDBM_update_generic(C, opdata->em, FALSE);
+	}
+
+	edbm_bevel_exit(C, op);
+
+	/* need to force redisplay or we may still view the modified result */
+	ED_region_tag_redraw(CTX_wm_region(C));
+	return OPERATOR_CANCELLED;
+}
+
+/* bevel! yay!!*/
+static int edbm_bevel_exec(bContext *C, wmOperator *op)
+{
+	if (!edbm_bevel_init(C, op, FALSE)) {
+		edbm_bevel_exit(C, op);
+		return OPERATOR_CANCELLED;
+	}
+
+	if (!edbm_bevel_calc(C, op)) {
+		edbm_bevel_cancel(C, op);
+		return OPERATOR_CANCELLED;
+	}
+
+	edbm_bevel_exit(C, op);
+
 	return OPERATOR_FINISHED;
 }
 
+static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+	/* TODO make modal keymap (see fly mode) */
+	BevelData *opdata;
+	float mlen[2];
+
+	if (!edbm_bevel_init(C, op, TRUE))
+		return OPERATOR_CANCELLED;
+
+	/* initialize mouse values */
+	opdata = op->customdata;
+
+	calculateTransformCenter(C, V3D_CENTROID, NULL, opdata->mcenter);
+	mlen[0] = opdata->mcenter[0] - event->mval[0];
+	mlen[1] = opdata->mcenter[1] - event->mval[1];
+	opdata->initial_length = len_v2(mlen);
+
+	edbm_bevel_update_header(op, C);
+
+	if (!edbm_bevel_calc(C, op)) {
+		edbm_bevel_cancel(C, op);
+		return OPERATOR_CANCELLED;
+	}
+
+	WM_event_add_modal_handler(C, op);
+
+	return OPERATOR_RUNNING_MODAL;
+}
+
+static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+	BevelData *opdata = op->customdata;
+//	Scene *scene = CTX_data_scene(C);
+
+	switch (event->type) {
+		case ESCKEY:
+		case RIGHTMOUSE:
+			edbm_bevel_cancel(C, op);
+			return OPERATOR_CANCELLED;
+
+		case MOUSEMOVE:
+		{
+			float factor;
+			float mdiff[2];
+
+			mdiff[0] = opdata->mcenter[0] - event->mval[0];
+			mdiff[1] = opdata->mcenter[1] - event->mval[1];
+
+			factor = len_v2(mdiff) / opdata->initial_length;
+			factor = MAX2(1.0 - factor, 0.0);
+
+			RNA_float_set(op->ptr, "percent", factor);
+
+			edbm_bevel_calc(C, op);
+			edbm_bevel_update_header(op, C);
+			return OPERATOR_RUNNING_MODAL;
+		}
+
+		case LEFTMOUSE:
+		case PADENTER:
+		case RETKEY:
+			edbm_bevel_calc(C, op);
+			edbm_bevel_exit(C, op);
+			return OPERATOR_FINISHED;
+
+		case EKEY:
+			if (event->val == KM_PRESS) {
+				int use_even =  RNA_boolean_get(op->ptr, "use_even");
+				RNA_boolean_set(op->ptr, "use_even", !use_even);
+
+				edbm_bevel_calc(C, op);
+				edbm_bevel_update_header(op, C);
+			}
+			return OPERATOR_RUNNING_MODAL;
+
+		case DKEY:
+			if (event->val == KM_PRESS) {
+				int use_dist =  RNA_boolean_get(op->ptr, "use_dist");
+				RNA_boolean_set(op->ptr, "use_dist", !use_dist);
+
+				edbm_bevel_calc(C, op);
+				edbm_bevel_update_header(op, C);
+			}
+			return OPERATOR_RUNNING_MODAL;
+	}
+
+	return OPERATOR_RUNNING_MODAL;
+}
+
 void MESH_OT_bevel(wmOperatorType *ot)
 {
 	/* identifiers */
@@ -4388,12 +4595,15 @@
 
 	/* api callbacks */
 	ot->exec = edbm_bevel_exec;
+	ot->invoke = edbm_bevel_invoke;
+	ot->modal = edbm_bevel_modal;
+	ot->cancel = edbm_bevel_cancel;
 	ot->poll = ED_operator_editmesh;
 
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
-	RNA_def_float(ot->srna, "percent", 0.5f, -FLT_MAX, FLT_MAX, "Percentage", "", 0.0f, 1.0f);

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list