[Bf-blender-cvs] [5d7d55c] temp_pie_max_items_fix: Pies: Support object mode pie with more than 8 items

Julian Eisel noreply at git.blender.org
Mon Feb 15 17:04:26 CET 2016


Commit: 5d7d55c1ef627f2769a2e80e3e5aa6636a8d9b32
Author: Julian Eisel
Date:   Mon Feb 15 15:28:56 2016 +0100
Branches: temp_pie_max_items_fix
https://developer.blender.org/rB5d7d55c1ef627f2769a2e80e3e5aa6636a8d9b32

Pies: Support object mode pie with more than 8 items

Fixes changing position of items introduced in rB669fdca6818b.
Since release is comming closer, I decided to try implementing support for more than 8 items per pie. This would require bigger changes which might not be safe to apply before relase though. For now, this should be good enough.

There are a few ugly things in the patch, but improving would not be trivial and require bigger changes. Was already tricky enough to get this working ;)

Reviewers: campbellbarton

Projects: #user_interface

Differential Revision: https://developer.blender.org/D1800

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

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_layout.c
M	source/blender/editors/interface/interface_regions.c

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

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 617b0d1..8c89b5d 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -978,6 +978,10 @@ void uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *pr
 void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
 void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *searchptr, const char *searchpropname, const char *name, int icon);
 void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname, struct IDProperty *properties, int context, int flag);
+void uiItemsFullEnumO_array(
+        uiLayout *layout, EnumPropertyItem *item_array, const int totitem,
+        struct wmOperatorType *ot, PointerRNA ptr, PropertyRNA *prop, const char *propname, IDProperty *properties,
+        const int context, const int flag);
 
 void uiItemL(uiLayout *layout, const char *name, int icon); /* label */
 void uiItemLDrag(uiLayout *layout, struct PointerRNA *ptr, const char *name, int icon); /* label icon for dragging */
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 06de5f9..4ceb216 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -182,6 +182,9 @@ enum {
 
 #define PIE_CLICK_THRESHOLD_SQ 50.0f
 
+/* max amount of items a radial menu (pie menu) can contain */
+#define PIE_MAX_ITEMS 8
+
 typedef struct uiLinkLine {  /* only for draw/edit */
 	struct uiLinkLine *next, *prev;
 	struct uiBut *from, *to;
@@ -332,6 +335,7 @@ typedef struct ColorPickerData {
 } ColorPickerData;
 
 struct PieMenuData {
+	const char *title;
 	float pie_dir[2];
 	float pie_center_init[2];
 	float pie_center_spawned[2];
@@ -603,6 +607,10 @@ uiPopupBlockHandle *ui_popup_menu_create(
         struct bContext *C, struct ARegion *butregion, uiBut *but,
         uiMenuCreateFunc create_func, void *arg);
 
+void ui_pie_menu_level_create(
+        uiBlock *block, struct wmOperatorType *ot, const char *propname, IDProperty *properties,
+        EnumPropertyItem *items, int totitem, int context, int flag);
+
 void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle);
 
 int  ui_but_menu_step(uiBut *but, int step);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 0b53232..5e83a65 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -883,6 +883,120 @@ void uiItemEnumO(uiLayout *layout, const char *opname, const char *name, int ico
 
 }
 
+static bool ui_layout_is_radial(const uiLayout *layout)
+{
+	return (layout->item.type == ITEM_LAYOUT_RADIAL) ||
+	       ((layout->item.type == ITEM_LAYOUT_ROOT) && (layout->root->type == UI_LAYOUT_PIEMENU));
+}
+
+/**
+ * Create ui items for enum items in \a item_array.
+ */
+void uiItemsFullEnumO_array(
+        uiLayout *layout, EnumPropertyItem *item_array, const int totitem,
+        wmOperatorType *ot, PointerRNA ptr, PropertyRNA *prop, const char *propname, IDProperty *properties,
+        const int context, const int flag)
+{
+	/* passing prop and ptr is optional, search for them if needed */
+	if (!ptr.data) {
+		WM_operator_properties_create_ptr(&ptr, ot);
+		/* so the context is passed to itemf functions (some need it) */
+		WM_operator_properties_sanitize(&ptr, false);
+	}
+	if (!prop) {
+		prop = RNA_struct_find_property(&ptr, propname);
+	}
+
+	if (!(prop && RNA_property_type(prop) == PROP_ENUM)) {
+		if (prop) {
+			RNA_warning("%s.%s, not an enum type", RNA_struct_identifier(ptr.type), propname);
+		}
+		else {
+			RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
+		}
+		return;
+	}
+
+
+	uiLayout *target, *split;
+	EnumPropertyItem *item;
+	uiBlock *block = layout->root->block;
+	const bool radial = ui_layout_is_radial(layout);
+	int i;
+
+	if (radial) {
+		target = uiLayoutRadial(layout);
+	}
+	else {
+		split = uiLayoutSplit(layout, 0.0f, false);
+		target = uiLayoutColumn(split, layout->align);
+	}
+
+	for (i = 1, item = item_array; item->identifier; i++, item++) {
+		/* handle oversized pies */
+		if (radial && i >= PIE_MAX_ITEMS) {
+			/* only create a new pie level if there's a visible item for it */
+			if (item->name) {
+				ui_pie_menu_level_create(block, ot, propname, properties, item_array, totitem, context, flag);
+				break;
+			}
+			continue;
+		}
+
+		if (item->identifier[0]) {
+			PointerRNA tptr;
+
+			WM_operator_properties_create_ptr(&tptr, ot);
+			if (properties) {
+				if (tptr.data) {
+					IDP_FreeProperty(tptr.data);
+					MEM_freeN(tptr.data);
+				}
+				tptr.data = IDP_CopyProperty(properties);
+			}
+			RNA_property_enum_set(&tptr, prop, item->value);
+
+			uiItemFullO_ptr(target, ot, item->name, item->icon, tptr.data, context, flag);
+
+			ui_but_tip_from_enum_item(block->buttons.last, item);
+		}
+		else {
+			if (item->name) {
+				uiBut *but;
+
+				if (item != item_array && !radial) {
+					target = uiLayoutColumn(split, target->align);
+
+					/* inconsistent, but menus with labels do not look good flipped */
+					block->flag |= UI_BLOCK_NO_FLIP;
+				}
+
+				if (item->icon || radial) {
+					uiItemL(target, item->name, item->icon);
+
+					but = block->buttons.last;
+				}
+				else {
+					/* Do not use uiItemL here, as our root layout is a menu one, it will add a fake blank icon! */
+					but = uiDefBut(block, UI_BTYPE_LABEL, 0, item->name, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL,
+					               0.0, 0.0, 0, 0, "");
+				}
+				ui_but_tip_from_enum_item(but, item);
+			}
+			else {
+				if (radial) {
+					/* invisible dummy button to ensure all items are always at the same position */
+					uiItemS(target);
+				}
+				else {
+					/* XXX bug here, colums draw bottom item badly */
+					uiItemS(target);
+				}
+			}
+		}
+	}
+}
+
 void uiItemsFullEnumO(
         uiLayout *layout, const char *opname, const char *propname, IDProperty *properties,
         int context, int flag)
@@ -892,8 +1006,6 @@ void uiItemsFullEnumO(
 	PointerRNA ptr;
 	PropertyRNA *prop;
 	uiBlock *block = layout->root->block;
-	const bool radial = (layout->item.type == ITEM_LAYOUT_RADIAL) ||
-	                     ((layout->item.type == ITEM_LAYOUT_ROOT) && (layout->root->type == UI_LAYOUT_PIEMENU));
 
 	if (!ot || !ot->srna) {
 		ui_item_disabled(layout, opname);
@@ -910,89 +1022,20 @@ void uiItemsFullEnumO(
 	BLI_assert((prop == NULL) || (RNA_property_type(prop) == PROP_ENUM));
 
 	if (prop && RNA_property_type(prop) == PROP_ENUM) {
-		EnumPropertyItem *item, *item_array = NULL;
+		EnumPropertyItem *item_array = NULL;
+		int totitem;
 		bool free;
-		uiLayout *split = NULL;
-		uiLayout *target;
 
-		if (radial) {
-			target = uiLayoutRadial(layout);
+		if (ui_layout_is_radial(layout)) {
+			RNA_property_enum_items_gettexted_all(block->evil_C, &ptr, prop, &item_array, &totitem, &free);
 		}
 		else {
-			split = uiLayoutSplit(layout, 0.0f, false);
-			target = uiLayoutColumn(split, layout->align);
-		}
-
-		if (0 && radial) {
-			/* XXX Disabled as temporary workaround!
-			 *
-			 * Normally, we always draw a button for all items even if they're unavailable (we draw invisible
-			 * dummy buttons then), so items are always at the same position. This causes issues with current
-			 * 'Object Mode' pie since more than 8 modes exist now (see T46973).
-			 * Disabling this until more than 8 items per pie are supported (or a better solution is found).
-			 * We should work on that ASAP though.
-			 *
-			 * - Julian (Dec 2015)
-			 */
-			RNA_property_enum_items_gettexted_all(block->evil_C, &ptr, prop, &item_array, NULL, &free);
-		}
-		else {
-			RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, NULL, &free);
+			RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, &totitem, &free);
 		}
 
-		for (item = item_array; item->identifier; item++) {
-			if (item->identifier[0]) {
-				PointerRNA tptr;
-
-				WM_operator_properties_create_ptr(&tptr, ot);
-				if (properties) {
-					if (tptr.data) {
-						IDP_FreeProperty(tptr.data);
-						MEM_freeN(tptr.data);
-					}
-					tptr.data = IDP_CopyProperty(properties);
-				}
-				RNA_property_enum_set(&tptr, prop, item->value);
-
-				uiItemFullO_ptr(target, ot, item->name, item->icon, tptr.data, context, flag);
-
-				ui_but_tip_from_enum_item(block->buttons.last, item);
-			}
-			else {
-				if (item->name) {
-					uiBut *but;
-
-					if (item != item_array && !radial) {
-						target = uiLayoutColumn(split, layout->align);
-
-						/* inconsistent, but menus with labels do not look good flipped */
-						block->flag |= UI_BLOCK_NO_FLIP;
-					}
-
-					if (item->icon || radial) {
-						uiItemL(target, item->name, item->icon);
+		/* add items */
+		uiItemsFullEnumO_array(layout, item_array, totitem, ot, ptr, prop, propname, properties, context, flag);
 
-						but = block->buttons.last;
-					}
-					else {
-						/* Do not use uiItemL here, as our root layout is a menu one, it will add a fake blank icon! */
-						but = uiDefBut(block, UI_BTYPE_LABEL, 0, item->name, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL,
-						               0.0, 0.0, 0, 0, "");
-					}
-					ui_but_tip_from_enum_item(but, item);
-				}
-				else {
-					if (radial) {
-						/* invisible dummy button to ensure all items are always at the same position */
-						uiItemS(target);
-					}
-					else {
-						/* XXX bug here, colums draw bottom item badly */
-						uiItemS(target);
-					}
-				}
-			}
-		}
 		if (free) {
 			MEM_freeN(item_array);
 		}
@@ -2178,9 +2221,9 @@ static RadialDirection ui_get_radialbut_vec(float vec[2], short itemnum)
 {
 	RadialDirection dir;
 
-	if (itemnum >= 8) {
-		itemnum %= 8;
-		printf("Warning: Pie menus with more than 8 items are currently unsupported\n");
+	if (itemnum >= PIE_MAX_ITEMS) {
+		itemnum %= PIE_MAX_ITEMS;
+		printf("Warning: Pie menus with more than %i items are currently unsupported\n", PIE_MAX_ITEMS);
 	}
 
 	dir 

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list