[Bf-blender-cvs] [733afd1] wiggly-widgets: Add more (face map) widget selection methods (shift+select, etc)

Julian Eisel noreply at git.blender.org
Fri Nov 27 22:17:42 CET 2015


Commit: 733afd16d709113fd29c71e8a74c862ae78de682
Author: Julian Eisel
Date:   Fri Nov 27 22:11:45 2015 +0100
Branches: wiggly-widgets
https://developer.blender.org/rB733afd16d709113fd29c71e8a74c862ae78de682

Add more (face map) widget selection methods (shift+select, etc)

Adds support for extending, deselecting and toggling widget selection, whereby only toggling has a default shortcut (shift+Selectmouse, just like everywhere).

Also naming cleanup.

===================================================================

M	source/blender/windowmanager/intern/wm_operators.c
M	source/blender/windowmanager/intern/wm_widgets.c
M	source/blender/windowmanager/wm.h
M	source/blender/windowmanager/wm_event_system.h

===================================================================

diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 08ff5cc..006b570 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -5331,7 +5331,7 @@ void wm_operatortype_init(void)
 
 	/* widgets */
 	WM_operatortype_append(WIDGETGROUP_OT_widget_set_active);
-	WM_operatortype_append(WIDGETGROUP_OT_widget_set_select);
+	WM_operatortype_append(WIDGETGROUP_OT_widget_select);
 	WM_operatortype_append(WIDGETGROUP_OT_widget_tweak);
 	WM_operatortype_append(WIDGETGROUP_OT_widget_tweak_cancel);
 }
diff --git a/source/blender/windowmanager/intern/wm_widgets.c b/source/blender/windowmanager/intern/wm_widgets.c
index a67d4fb..25017c8 100644
--- a/source/blender/windowmanager/intern/wm_widgets.c
+++ b/source/blender/windowmanager/intern/wm_widgets.c
@@ -702,18 +702,193 @@ void WIDGETGROUP_OT_widget_set_active(wmOperatorType *ot)
 	RNA_def_boolean(ot->srna, "deactivate", 0, "Deactivate", "Deactivate currently active widget");
 }
 
-static int widget_set_select_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+/**
+ * Deselect all selected widgets in \a wmap.
+ * \return if selection has changed.
+ */
+static bool wm_widgetmap_deselect_all(wmWidgetMap *wmap, wmWidget ***sel)
+{
+	if (*sel == NULL || wmap->wmap_context.tot_selected == 0)
+		return false;
+
+	for (int i = 0; i < wmap->wmap_context.tot_selected; i++) {
+		(*sel)[i]->flag &= ~WM_WIDGET_SELECTED;
+		(*sel)[i] = NULL;
+	}
+	MEM_SAFE_FREE(*sel);
+	wmap->wmap_context.tot_selected = 0;
+
+	/* always return true, we already checked
+	 * if there's anything to deselect */
+	return true;
+}
+
+BLI_INLINE bool widget_selectable_poll(const wmWidget *widget, void *UNUSED(data))
+{
+	return (widget->flag & WM_WIDGET_SELECTABLE);
+}
+
+/**
+ * Select all selectable widgets in \a wmap.
+ * \return if selection has changed.
+ */
+static bool wm_widgetmap_select_all_intern(bContext *C, wmWidgetMap *wmap, wmWidget ***sel, const int action)
+{
+	/* GHash is used here to avoid having to loop over all widgets twice (once to
+	 * get tot_sel for allocating, once for actually selecting). Instead we collect
+	 * selectable widgets in hash table and use this to get tot_sel and do selection */
+
+	GHash *hash = wm_widgetmap_widget_hash_new(C, wmap, widget_selectable_poll, NULL, true);
+	GHashIterator gh_iter;
+	int i, *tot_sel = &wmap->wmap_context.tot_selected;
+	bool changed = false;
+
+	*tot_sel = BLI_ghash_size(hash);
+	*sel = MEM_reallocN(*sel, sizeof(**sel) * (*tot_sel));
+
+	GHASH_ITER_INDEX (gh_iter, hash, i) {
+		wmWidget *widget_iter = BLI_ghashIterator_getValue(&gh_iter);
+
+		if ((widget_iter->flag & WM_WIDGET_SELECTED) == 0) {
+			changed = true;
+		}
+		widget_iter->flag |= WM_WIDGET_SELECTED;
+		if (widget_iter->select) {
+			widget_iter->select(C, widget_iter, action);
+		}
+		(*sel)[i] = widget_iter;
+		BLI_assert(i < (*tot_sel));
+	}
+	/* highlight first widget */
+	wm_widgetmap_set_highlighted_widget(wmap, C, (*sel)[0], (*sel)[0]->highlighted_part);
+
+	BLI_ghash_free(hash, NULL, NULL);
+	return changed;
+}
+
+/**
+ * Select/Deselect all selectable widgets in \a wmap.
+ * \return if selection has changed.
+ *
+ * TODO select all by type
+ */
+bool WM_widgetmap_select_all(bContext *C, wmWidgetMap *wmap, const int action)
+{
+	wmWidget ***sel = &wmap->wmap_context.selected_widgets;
+	bool changed = false;
+
+	switch (action) {
+		case SEL_SELECT:
+			changed = wm_widgetmap_select_all_intern(C, wmap, sel, action);
+			break;
+		case SEL_DESELECT:
+			changed = wm_widgetmap_deselect_all(wmap, sel);
+			break;
+		default:
+			BLI_assert(0);
+	}
+
+	return changed;
+}
+
+/**
+ * Remove \a widget from selection
+ * Re-allocates memory for selected widgets so better not call for selecting multiple ones.
+ */
+static void wm_widget_deselect(const bContext *C, wmWidgetMap *wmap, wmWidget *widget)
+{
+	wmWidget ***sel = &wmap->wmap_context.selected_widgets;
+	int *tot_selected = &wmap->wmap_context.tot_selected;
+
+	/* caller should check! */
+	BLI_assert(widget->flag & WM_WIDGET_SELECTED);
+
+	/* remove widget from selected_widgets array */
+	for (int i = 0; i < (*tot_selected); i++) {
+		if (widget_compare((*sel)[i], widget)) {
+			for (int j = i; j < ((*tot_selected) - 1); j++) {
+				(*sel)[j] = (*sel)[j + 1];
+			}
+		}
+	}
+
+	/* update array data */
+	if ((*tot_selected) <= 1) {
+		MEM_SAFE_FREE(*sel);
+		*tot_selected = 0;
+	}
+	else {
+		*sel = MEM_reallocN(*sel, sizeof(**sel) * (*tot_selected));
+		(*tot_selected)--;
+	}
+
+	widget->flag &= ~WM_WIDGET_SELECTED;
+
+	ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+/**
+ * Add \a widget to selection
+ * Reallocate memory for selected widgets so better not call for selecting multiple ones.
+ */
+void wm_widget_select(bContext *C, wmWidgetMap *wmap, wmWidget *widget)
+{
+	wmWidget ***sel = &wmap->wmap_context.selected_widgets;
+	int *tot_selected = &wmap->wmap_context.tot_selected;
+
+	if (!widget || (widget->flag & WM_WIDGET_SELECTED))
+		return;
+
+	(*tot_selected)++;
+
+	*sel = MEM_reallocN(*sel, sizeof(**sel) * (*tot_selected));
+	(*sel)[(*tot_selected) - 1] = widget;
+
+	widget->flag |= WM_WIDGET_SELECTED;
+	if (widget->select) {
+		widget->select(C, widget, SEL_SELECT);
+	}
+	wm_widgetmap_set_highlighted_widget(wmap, C, widget, widget->highlighted_part);
+
+	ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+static int widget_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
 {
 	ARegion *ar = CTX_wm_region(C);
 
+	bool extend = RNA_boolean_get(op->ptr, "extend");
+	bool deselect = RNA_boolean_get(op->ptr, "deselect");
+	bool toggle = RNA_boolean_get(op->ptr, "toggle");
+
+
 	for (wmWidgetMap *wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) {
-		wmWidget *widget = wmap->wmap_context.highlighted_widget;
-		if (widget) {
-			if (widget->flag & WM_WIDGET_SELECTABLE) {
-				wm_widgetmap_select_widget(C, wmap, widget);
-				return OPERATOR_FINISHED;
+		wmWidget ***sel = &wmap->wmap_context.selected_widgets;
+		wmWidget *highlighted = wmap->wmap_context.highlighted_widget;
+
+		/* deselect all first */
+		if (extend == false && deselect == false && toggle == false) {
+			wm_widgetmap_deselect_all(wmap, sel);
+			BLI_assert(*sel == NULL && wmap->wmap_context.tot_selected == 0);
+		}
+
+		if (highlighted) {
+			const bool is_selected = (highlighted->flag & WM_WIDGET_SELECTED);
+
+			if (toggle) {
+				/* toggle: deselect if already selected, else select */
+				deselect = is_selected;
 			}
-			break;
+
+			if (deselect) {
+				if (is_selected)
+					wm_widget_deselect(C, wmap, highlighted);
+			}
+			else {
+				wm_widget_select(C, wmap, highlighted);
+			}
+
+			return OPERATOR_FINISHED;
 		}
 		else {
 			BLI_assert(0);
@@ -724,20 +899,19 @@ static int widget_set_select_invoke(bContext *C, wmOperator *UNUSED(op), const w
 	return OPERATOR_PASS_THROUGH;
 }
 
-void WIDGETGROUP_OT_widget_set_select(wmOperatorType *ot)
+void WIDGETGROUP_OT_widget_select(wmOperatorType *ot)
 {
 	/* identifiers */
 	ot->name = "Widget Select";
 	ot->description = "Select the currently highlighted widget";
-	ot->idname = "WIDGETGROUP_OT_widget_set_select";
+	ot->idname = "WIDGETGROUP_OT_widget_select";
 
 	/* api callbacks */
-	ot->invoke = widget_set_select_invoke;
+	ot->invoke = widget_select_invoke;
 
 	ot->flag = OPTYPE_UNDO;
 
-	/* TODO - more fancy selections are not implemented yet */
-//	RNA_def_boolean(ot->srna, "deactivate", 0, "Deactivate", "Deactivate currently active widget");
+	WM_operator_properties_mouse_select(ot);
 }
 
 static int widget_tweak_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
@@ -1118,120 +1292,6 @@ void wm_widgetmap_set_active_widget(
 	}
 }
 
-/**
- * Deselect all selected widgets in \a wmap.
- * \return if selection has changed.
- */
-static bool wm_widgetmap_deselect_all(wmWidgetMap *wmap, wmWidget ***sel)
-{
-	if (*sel == NULL || wmap->wmap_context.tot_selected == 0)
-		return false;
-
-	for (int i = 0; i < wmap->wmap_context.tot_selected; i++) {
-		(*sel)[i]->flag &= ~WM_WIDGET_SELECTED;
-		(*sel)[i] = NULL;
-	}
-	MEM_SAFE_FREE(*sel);
-	wmap->wmap_context.tot_selected = 0;
-
-	/* always return true, we already checked
-	 * if there's anything to deselect */
-	return true;
-}
-
-BLI_INLINE bool widget_selectable_poll(const wmWidget *widget, void *UNUSED(data))
-{
-	return (widget->flag & WM_WIDGET_SELECTABLE);
-}
-
-/**
- * Select all selectable widgets in \a wmap.
- * \return if selection has changed.
- */
-static bool wm_widgetmap_select_all_intern(bContext *C, wmWidgetMap *wmap, wmWidget ***sel, const int action)
-{
-	/* GHash is used here to avoid having to loop over all widgets twice (once to
-	 * get tot_sel for allocating, once for actually selecting). Instead we collect
-	 * selectable widgets in hash table and use this to get tot_sel and do selection */
-
-	GHash *hash = wm_widgetmap_widget_hash_new(C, wmap, widget_selectable_poll, NULL, true);
-	GHashIterator gh_iter;
-	int i, *tot_sel = &wmap->wmap_context.tot_selected;
-	bool changed = false;
-
-	*tot_sel = BLI_ghash_size(hash);
-	*sel = MEM_reallocN(*sel, sizeof(**sel) * (*tot_sel));
-
-	GHASH_ITER_INDEX (gh_iter, hash, i) {
-		wmWidget *widget_iter = BLI_ghashIterator_getValue(&gh_iter);
-
-		if ((widget_iter->flag & WM_WIDGET_SELECTED) == 0) {
-			changed = true;
-		}
-		widget_iter->flag |= WM_WIDGET_SELECTED;
-		if (widget_iter->select) {
-			widget_iter->select(C, widget_iter, action);
-		}
-		(*sel)[i] = widget_iter;
-		BLI_assert(i < (*tot_sel));
-	}
-	/* highlight first widget */
-	wm_widgetmap_set_highlighted_widget(wmap, C, (*sel)[0], (*sel)[0]->highlighted_part);
-
-	BLI_ghash_free(hash, NULL, NULL);
-	return changed;
-}
-
-/**
- * Select/Deselect all selectable widgets in \a wmap.
- * \return if selection has changed.
- *
- * TODO select all by type
- */
-bool WM_widgetmap_select_all(bContext *C, wmWidgetMap *wmap, const int action)
-{
-	wmWidget ***sel = &wmap->wmap_context.selected_widgets;
-	bool changed = false;
-
-	switch (action) {
-		case SEL_SELECT:
-			changed = wm_widgetmap_select_all_intern(C, wmap, sel, action);
-			break;
-		case SEL_DESELECT:
-			changed = wm

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list