diff --git a/doc/python_api/examples/bpy.types.UIList.2.py b/doc/python_api/examples/bpy.types.UIList.2.py index 05c9e9b3a17..5a36036803e 100644 --- a/doc/python_api/examples/bpy.types.UIList.2.py +++ b/doc/python_api/examples/bpy.types.UIList.2.py @@ -136,8 +136,9 @@ class MESH_UL_vgroups_slow(bpy.types.UIList): def filter_items(self, context, data, propname): # This function gets the collection property (as the usual tuple (data, propname)), and must return two lists: # * The first one is for filtering, it must contain 32bit integers were self.bitflag_filter_item marks the - # matching item as filtered (i.e. to be shown), and 31 other bits are free for custom needs. Here we use the - # first one to mark VGROUP_EMPTY. + # matching item as filtered (i.e. to be shown). The upper 16 bits (including self.bitflag_filter_item) are + # reserved for internal use, the lower 16 bits are free for custom use. Here we use the first bit to mark + # VGROUP_EMPTY. # * The second one is for reordering, it must return a list containing the new indices of the items (which # gives us a mapping org_idx -> new_idx). # Please note that the default UI_UL_list defines helper functions for common tasks (see its doc for more info). diff --git a/scripts/templates_py/ui_list.py b/scripts/templates_py/ui_list.py index 9727a1b3678..c5700e9970c 100644 --- a/scripts/templates_py/ui_list.py +++ b/scripts/templates_py/ui_list.py @@ -30,8 +30,9 @@ class MESH_UL_mylist(bpy.types.UIList): def filter_items(self, context, data, propname): # This function gets the collection property (as the usual tuple (data, propname)), and must return two lists: # * The first one is for filtering, it must contain 32bit integers were self.bitflag_filter_item marks the - # matching item as filtered (i.e. to be shown), and 31 other bits are free for custom needs. Here we use the - # first one to mark VGROUP_EMPTY. + # matching item as filtered (i.e. to be shown). The upper 16 bits (including self.bitflag_filter_item) are + # reseverd for internal use, the lower 16 bits are free for custom use. Here we use the first bit to mark + # VGROUP_EMPTY. # * The second one is for reordering, it must return a list containing the new indices of the items (which # gives us a mapping org_idx -> new_idx). # Please note that the default UI_UL_list defines helper functions for common tasks (see its doc for more info). diff --git a/source/blender/editors/interface/interface_handlers.cc b/source/blender/editors/interface/interface_handlers.cc index 493c73479c1..646f614430b 100644 --- a/source/blender/editors/interface/interface_handlers.cc +++ b/source/blender/editors/interface/interface_handlers.cc @@ -9774,7 +9774,8 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *regi for (int i = 0; i < len; i++) { if (!dyn_data->items_filter_flags || - ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) + (((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM_NEVER_SHOW) == 0) && + (dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) { org_order[new_order ? new_order[++org_idx] : ++org_idx] = i; if (i == value) { diff --git a/source/blender/editors/interface/interface_template_list.cc b/source/blender/editors/interface/interface_template_list.cc index af6c7f7a577..8d18ac9d55b 100644 --- a/source/blender/editors/interface/interface_template_list.cc +++ b/source/blender/editors/interface/interface_template_list.cc @@ -250,7 +250,7 @@ void UI_list_filter_and_sort_items(uiList *ui_list, const eUIListFilterResult filter_result = item_filter_fn(itemptr, name, i); if (filter_result == UI_LIST_ITEM_NEVER_SHOW) { - /* Pass. */ + dyn_data->items_filter_flags[i] = UILST_FLT_ITEM_NEVER_SHOW; } else if (filter_result == UI_LIST_ITEM_FILTER_MATCHES) { dyn_data->items_filter_flags[i] = UILST_FLT_ITEM; @@ -431,7 +431,8 @@ static void ui_template_list_collect_items(PointerRNA *list_ptr, RNA_PROP_BEGIN (list_ptr, itemptr, list_prop) { if (!dyn_data->items_filter_flags || - ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) + (((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM_NEVER_SHOW) == 0) && + ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude))) { int new_order_idx; if (dyn_data->items_filter_neworder) { diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 7bd59a3c1fd..71d4d52b3cf 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -275,7 +275,9 @@ typedef struct uiListDyn { void *customdata; /* Filtering data. */ - /** Items_len length. */ + /** This bitfield is effectively exposed in Python, and scripts are explicitly allowed to assign + * any own meaning to the lower 16 ones. + * #items_len length. */ int *items_filter_flags; /** Org_idx -> new_idx, items_len length. */ int *items_filter_neworder; @@ -626,10 +628,18 @@ enum { /** Value (in number of items) we have to go below minimum shown items to enable auto size. */ #define UI_LIST_AUTO_SIZE_THRESHOLD 1 -/* uiList filter flags (dyn_data) */ -/* WARNING! Those values are used by integer RNA too, which does not handle well values > INT_MAX. - * So please do not use 32nd bit here. */ +/** uiList filter flags (dyn_data) + * + * \warning Lower 16 bits are meant for custom use in Python, don't use them here! Only use the + * higher 16 bits. + * \warning Those values are used by integer RNA too, which does not handle well values > INT_MAX. + * So please do not use 32nd bit here. + */ enum { + /* Don't use (1 << 0) to (1 << 15) here! See warning above. */ + + /* Filtering returned #UI_LIST_ITEM_NEVER_SHOW. */ + UILST_FLT_ITEM_NEVER_SHOW = (1 << 16), UILST_FLT_ITEM = 1 << 30, /* This item has passed the filter process successfully. */ }; diff --git a/source/blender/makesrna/intern/rna_ui.cc b/source/blender/makesrna/intern/rna_ui.cc index 085b4773937..a79c933fed6 100644 --- a/source/blender/makesrna/intern/rna_ui.cc +++ b/source/blender/makesrna/intern/rna_ui.cc @@ -625,7 +625,10 @@ static void uilist_filter_items(uiList *ui_list, int t_idx, t_ni, prev_ni; flt_data->items_shown = 0; for (i = 0, shown_idx = 0; i < len; i++) { - if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) { + if (filter_flags[i] & UILST_FLT_ITEM_NEVER_SHOW) { + BLI_assert_msg(false, "Bit reserved for internal use"); + } + else if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) { filter_neworder[shown_idx++] = filter_neworder[i]; } } @@ -653,7 +656,10 @@ static void uilist_filter_items(uiList *ui_list, /* we still have to set flt_data->items_shown... */ flt_data->items_shown = 0; for (i = 0; i < len; i++) { - if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) { + if (filter_flags[i] & UILST_FLT_ITEM_NEVER_SHOW) { + /* Pass. */ + } + else if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) { flt_data->items_shown++; } } @@ -2073,11 +2079,11 @@ static void rna_def_uilist(BlenderRNA *brna) prop = RNA_def_property(func, "filter_flags", PROP_INT, PROP_UNSIGNED); RNA_def_property_flag(prop, PropertyFlag(PARM_REQUIRED | PROP_DYNAMIC)); RNA_def_property_array(prop, 1); /* XXX Dummy value, default 0 does not work */ - RNA_def_property_ui_text( - prop, - "", - "An array of filter flags, one for each item in the collection (NOTE: " - "FILTER_ITEM bit is reserved, it defines whether the item is shown or not)"); + RNA_def_property_ui_text(prop, + "", + "An array of filter flags, one for each item in the collection (NOTE: " + "The upper 16 bits, including FILTER_ITEM, are reserved, only use the " + "lower 16 bits for custom usages)."); RNA_def_function_output(func, prop); prop = RNA_def_property(func, "filter_neworder", PROP_INT, PROP_UNSIGNED); RNA_def_property_flag(prop, PropertyFlag(PARM_REQUIRED | PROP_DYNAMIC));