Compare commits
12 Commits
temp-defor
...
temp-ui-bu
Author | SHA1 | Date | |
---|---|---|---|
0d2d4a6d4a | |||
9b416c66fb | |||
89dbb12c29 | |||
4de632b48b | |||
2400160bc4 | |||
a903f7c243 | |||
2a515fe612 | |||
190ef51fd5 | |||
51afd98b1d | |||
6609fa2996 | |||
b4f92bf7bc | |||
dc9df6540c |
@@ -57,6 +57,7 @@ struct bNodeSocket;
|
||||
struct bNodeTree;
|
||||
struct bScreen;
|
||||
struct rcti;
|
||||
struct uiButSearch;
|
||||
struct uiFontStyle;
|
||||
struct uiList;
|
||||
struct uiStyle;
|
||||
@@ -371,6 +372,7 @@ typedef enum {
|
||||
UI_BTYPE_SEPR_SPACER = 56 << 9,
|
||||
/** Resize handle (resize uilist). */
|
||||
UI_BTYPE_GRIP = 57 << 9,
|
||||
UI_BTYPE_DECORATOR = 58 << 9,
|
||||
} eButType;
|
||||
|
||||
#define BUTTYPE (63 << 9)
|
||||
@@ -388,8 +390,6 @@ enum {
|
||||
UI_GRAD_L_ALT = 10,
|
||||
};
|
||||
|
||||
#define UI_PALETTE_COLOR 20
|
||||
|
||||
/* Drawing
|
||||
*
|
||||
* Functions to draw various shapes, taking theme settings into account.
|
||||
@@ -500,7 +500,7 @@ typedef int (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg);
|
||||
/* Search types. */
|
||||
typedef struct ARegion *(*uiButSearchCreateFn)(struct bContext *C,
|
||||
struct ARegion *butregion,
|
||||
uiBut *but);
|
||||
struct uiButSearch *search_but);
|
||||
typedef void (*uiButSearchUpdateFn)(const struct bContext *C,
|
||||
void *arg,
|
||||
const char *str,
|
||||
@@ -537,7 +537,7 @@ typedef bool (*uiMenuStepFunc)(struct bContext *C, int direction, void *arg1);
|
||||
bool UI_but_has_tooltip_label(const uiBut *but);
|
||||
bool UI_but_is_tool(const uiBut *but);
|
||||
bool UI_but_is_utf8(const uiBut *but);
|
||||
#define UI_but_is_decorator(but) ((but)->func == ui_but_anim_decorate_cb)
|
||||
#define UI_but_is_decorator(but) ((but)->type == UI_BTYPE_DECORATOR)
|
||||
|
||||
bool UI_block_is_empty_ex(const uiBlock *block, const bool skip_title);
|
||||
bool UI_block_is_empty(const uiBlock *block);
|
||||
@@ -1929,8 +1929,6 @@ uiLayout *uiLayoutGridFlow(uiLayout *layout,
|
||||
uiLayout *uiLayoutBox(uiLayout *layout);
|
||||
uiLayout *uiLayoutListBox(uiLayout *layout,
|
||||
struct uiList *ui_list,
|
||||
struct PointerRNA *ptr,
|
||||
struct PropertyRNA *prop,
|
||||
struct PointerRNA *actptr,
|
||||
struct PropertyRNA *actprop);
|
||||
uiLayout *uiLayoutAbsolute(uiLayout *layout, bool align);
|
||||
|
@@ -807,7 +807,12 @@ static bool ui_but_update_from_old_block(const bContext *C,
|
||||
|
||||
SWAP(ListBase, but->extra_op_icons, oldbut->extra_op_icons);
|
||||
|
||||
SWAP(struct uiButSearchData *, oldbut->search, but->search);
|
||||
if (oldbut->type == UI_BTYPE_SEARCH_MENU) {
|
||||
uiButSearch *search_oldbut = (uiButSearch *)oldbut, *search_but = (uiButSearch *)but;
|
||||
|
||||
SWAP(uiButSearchArgFreeFn, search_oldbut->arg_free_fn, search_but->arg_free_fn);
|
||||
SWAP(void *, search_oldbut->arg, search_but->arg);
|
||||
}
|
||||
|
||||
/* copy hardmin for list rows to prevent 'sticking' highlight to mouse position
|
||||
* when scrolling without moving mouse (see [#28432]) */
|
||||
@@ -815,10 +820,10 @@ static bool ui_but_update_from_old_block(const bContext *C,
|
||||
oldbut->hardmax = but->hardmax;
|
||||
}
|
||||
|
||||
/* Selectively copy a1, a2 since their use differs across all button types
|
||||
* (and we'll probably split these out later) */
|
||||
if (ELEM(oldbut->type, UI_BTYPE_PROGRESS_BAR)) {
|
||||
oldbut->a1 = but->a1;
|
||||
if (oldbut->type == UI_BTYPE_PROGRESS_BAR) {
|
||||
uiButProgressbar *progress_oldbut = (uiButProgressbar *)oldbut;
|
||||
uiButProgressbar *progress_but = (uiButProgressbar *)but;
|
||||
progress_oldbut->progress = progress_but->progress;
|
||||
}
|
||||
|
||||
if (!BLI_listbase_is_empty(&block->butstore)) {
|
||||
@@ -1773,7 +1778,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
|
||||
ui_but_anim_flag(but, &anim_eval_context);
|
||||
ui_but_override_flag(CTX_data_main(C), but);
|
||||
if (UI_but_is_decorator(but)) {
|
||||
ui_but_anim_decorate_update_from_flag(but);
|
||||
ui_but_anim_decorate_update_from_flag((uiButDecorator *)but);
|
||||
}
|
||||
ui_but_predefined_extra_operator_icons_add(but);
|
||||
}
|
||||
@@ -2021,6 +2026,7 @@ int ui_but_is_pushed_ex(uiBut *but, double *value)
|
||||
case UI_BTYPE_HOTKEY_EVENT:
|
||||
case UI_BTYPE_KEY_EVENT:
|
||||
case UI_BTYPE_COLOR:
|
||||
case UI_BTYPE_DECORATOR:
|
||||
is_push = -1;
|
||||
break;
|
||||
case UI_BTYPE_BUT_TOGGLE:
|
||||
@@ -2323,7 +2329,8 @@ bool ui_but_supports_cycling(const uiBut *but)
|
||||
{
|
||||
return ((ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_LISTBOX)) ||
|
||||
(but->type == UI_BTYPE_MENU && ui_but_menu_step_poll(but)) ||
|
||||
(but->type == UI_BTYPE_COLOR && but->a1 != -1) || (but->menu_step_func != NULL));
|
||||
(but->type == UI_BTYPE_COLOR && ((uiButColor *)but)->is_pallete_color) ||
|
||||
(but->menu_step_func != NULL));
|
||||
}
|
||||
|
||||
double ui_but_value_get(uiBut *but)
|
||||
@@ -2945,10 +2952,10 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
|
||||
RNA_property_pointer_set(&but->rnapoin, but->rnaprop, PointerRNA_NULL, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
uiButSearch *search_but = (but->type == UI_BTYPE_SEARCH_MENU) ? (uiButSearch *)but : NULL;
|
||||
/* RNA pointer */
|
||||
PointerRNA rptr;
|
||||
PointerRNA ptr = but->rnasearchpoin;
|
||||
PropertyRNA *prop = but->rnasearchprop;
|
||||
|
||||
/* This is kind of hackish, in theory think we could only ever use the second member of
|
||||
* this if/else, since ui_searchbox_apply() is supposed to always set that pointer when
|
||||
@@ -2956,12 +2963,16 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
|
||||
* to try to break as little as possible existing code. All this is band-aids anyway.
|
||||
* Fact remains, using editstr as main 'reference' over whole search button thingy
|
||||
* is utterly weak and should be redesigned imho, but that's not a simple task. */
|
||||
if (prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) {
|
||||
if (search_but && search_but->rnasearchprop &&
|
||||
RNA_property_collection_lookup_string(
|
||||
&search_but->rnasearchpoin, search_but->rnasearchprop, str, &rptr)) {
|
||||
RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr, NULL);
|
||||
}
|
||||
else if (but->func_arg2 != NULL) {
|
||||
RNA_pointer_create(
|
||||
NULL, RNA_property_pointer_type(&but->rnapoin, but->rnaprop), but->func_arg2, &rptr);
|
||||
else if (search_but->item_active != NULL) {
|
||||
RNA_pointer_create(NULL,
|
||||
RNA_property_pointer_type(&but->rnapoin, but->rnaprop),
|
||||
search_but->item_active,
|
||||
&rptr);
|
||||
RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr, NULL);
|
||||
}
|
||||
|
||||
@@ -3231,6 +3242,28 @@ void ui_but_range_set_soft(uiBut *but)
|
||||
|
||||
/* ******************* Free ********************/
|
||||
|
||||
/**
|
||||
* Free data specific to a certain button type.
|
||||
* For now just do in a switch-case, we could instead have a callback stored in #uiBut and set that
|
||||
* in #ui_but_alloc_info().
|
||||
*/
|
||||
static void ui_but_free_type_specific(uiBut *but)
|
||||
{
|
||||
switch (but->type) {
|
||||
case UI_BTYPE_SEARCH_MENU: {
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
|
||||
if (search_but->arg_free_fn) {
|
||||
search_but->arg_free_fn(search_but->arg);
|
||||
search_but->arg = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* can be called with C==NULL */
|
||||
static void ui_but_free(const bContext *C, uiBut *but)
|
||||
{
|
||||
@@ -3251,13 +3284,7 @@ static void ui_but_free(const bContext *C, uiBut *but)
|
||||
MEM_freeN(but->hold_argN);
|
||||
}
|
||||
|
||||
if (but->search != NULL) {
|
||||
if (but->search->arg_free_fn) {
|
||||
but->search->arg_free_fn(but->search->arg);
|
||||
but->search->arg = NULL;
|
||||
}
|
||||
MEM_freeN(but->search);
|
||||
}
|
||||
ui_but_free_type_specific(but);
|
||||
|
||||
if (but->active) {
|
||||
/* XXX solve later, buttons should be free-able without context ideally,
|
||||
@@ -3736,14 +3763,107 @@ void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3])
|
||||
IMB_colormanagement_scene_linear_to_display_v3(pixel, display);
|
||||
}
|
||||
|
||||
static void ui_but_alloc_info(const eButType type,
|
||||
size_t *r_alloc_size,
|
||||
const char **r_alloc_str,
|
||||
bool *r_has_custom_type)
|
||||
{
|
||||
size_t alloc_size;
|
||||
const char *alloc_str;
|
||||
bool has_custom_type = true;
|
||||
|
||||
switch (type) {
|
||||
case UI_BTYPE_COLOR:
|
||||
alloc_size = sizeof(uiButColor);
|
||||
alloc_str = "uiButColor";
|
||||
break;
|
||||
case UI_BTYPE_DECORATOR:
|
||||
alloc_size = sizeof(uiButDecorator);
|
||||
alloc_str = "uiButDecorator";
|
||||
break;
|
||||
case UI_BTYPE_TAB:
|
||||
alloc_size = sizeof(uiButTab);
|
||||
alloc_str = "uiButTab";
|
||||
break;
|
||||
case UI_BTYPE_SEARCH_MENU:
|
||||
alloc_size = sizeof(uiButSearch);
|
||||
alloc_str = "uiButSearch";
|
||||
break;
|
||||
case UI_BTYPE_PROGRESS_BAR:
|
||||
alloc_size = sizeof(uiButProgressbar);
|
||||
alloc_str = "uiButProgressbar";
|
||||
break;
|
||||
default:
|
||||
alloc_size = sizeof(uiBut);
|
||||
alloc_str = "uiBut";
|
||||
has_custom_type = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (r_alloc_size) {
|
||||
*r_alloc_size = alloc_size;
|
||||
}
|
||||
if (r_alloc_str) {
|
||||
*r_alloc_str = alloc_str;
|
||||
}
|
||||
if (r_has_custom_type) {
|
||||
*r_has_custom_type = has_custom_type;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBut *ui_but_alloc(const eButType type)
|
||||
{
|
||||
switch (type) {
|
||||
case UI_BTYPE_TAB:
|
||||
return MEM_callocN(sizeof(uiButTab), "uiButTab");
|
||||
default:
|
||||
return MEM_callocN(sizeof(uiBut), "uiBut");
|
||||
size_t alloc_size;
|
||||
const char *alloc_str;
|
||||
|
||||
ui_but_alloc_info(type, &alloc_size, &alloc_str, NULL);
|
||||
|
||||
return MEM_callocN(alloc_size, alloc_str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reallocate the button (new address is returned) for a new button type.
|
||||
* This should generally be avoided and instead the correct type be created right away.
|
||||
*
|
||||
* \note Only the #uiBut data can be kept. If the old button used a derived type (e.g. #uiButTab),
|
||||
* the data that is not inside #uiBut will be lost.
|
||||
*/
|
||||
uiBut *ui_but_change_type(uiBut *but, eButType new_type)
|
||||
{
|
||||
if (but->type != new_type) {
|
||||
size_t alloc_size;
|
||||
const char *alloc_str;
|
||||
uiBut *insert_after_but = but->prev;
|
||||
bool new_has_custom_type, old_has_custom_type;
|
||||
|
||||
/* Remove old button address */
|
||||
BLI_remlink(&but->block->buttons, but);
|
||||
|
||||
ui_but_alloc_info(but->type, NULL, NULL, &old_has_custom_type);
|
||||
ui_but_alloc_info(new_type, &alloc_size, &alloc_str, &new_has_custom_type);
|
||||
|
||||
if (new_has_custom_type || old_has_custom_type) {
|
||||
const void *old_but_ptr = but;
|
||||
/* Button may have pointer to a member within itself, this will have to be updated. */
|
||||
const bool has_str_ptr_to_self = but->str == but->strdata;
|
||||
|
||||
but = MEM_recallocN_id(but, alloc_size, alloc_str);
|
||||
but->type = new_type;
|
||||
if (has_str_ptr_to_self) {
|
||||
but->str = but->strdata;
|
||||
}
|
||||
|
||||
BLI_insertlinkafter(&but->block->buttons, insert_after_but, but);
|
||||
|
||||
if (but->layout) {
|
||||
const bool found_layout = ui_layout_replace_but_ptr(but->layout, old_but_ptr, but);
|
||||
BLI_assert(found_layout);
|
||||
UNUSED_VARS_NDEBUG(found_layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return but;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3891,6 +4011,7 @@ static uiBut *ui_def_but(uiBlock *block,
|
||||
if (ELEM(but->type,
|
||||
UI_BTYPE_BLOCK,
|
||||
UI_BTYPE_BUT,
|
||||
UI_BTYPE_DECORATOR,
|
||||
UI_BTYPE_LABEL,
|
||||
UI_BTYPE_PULLDOWN,
|
||||
UI_BTYPE_ROUNDBOX,
|
||||
@@ -6385,54 +6506,55 @@ void UI_but_func_search_set(uiBut *but,
|
||||
uiButHandleFunc search_exec_fn,
|
||||
void *active)
|
||||
{
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
|
||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
||||
|
||||
/* needed since callers don't have access to internal functions
|
||||
* (as an alternative we could expose it) */
|
||||
if (search_create_fn == NULL) {
|
||||
search_create_fn = ui_searchbox_create_generic;
|
||||
}
|
||||
|
||||
struct uiButSearchData *search = but->search;
|
||||
if (search != NULL) {
|
||||
if (search->arg_free_fn != NULL) {
|
||||
search->arg_free_fn(but->search->arg);
|
||||
search->arg = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
search = MEM_callocN(sizeof(*but->search), __func__);
|
||||
but->search = search;
|
||||
if (search_but->arg_free_fn != NULL) {
|
||||
search_but->arg_free_fn(search_but->arg);
|
||||
search_but->arg = NULL;
|
||||
}
|
||||
|
||||
search->create_fn = search_create_fn;
|
||||
search->update_fn = search_update_fn;
|
||||
search_but->popup_create_fn = search_create_fn;
|
||||
search_but->items_update_fn = search_update_fn;
|
||||
search_but->item_active = active;
|
||||
|
||||
search->arg = arg;
|
||||
search->arg_free_fn = search_arg_free_fn;
|
||||
search_but->arg = arg;
|
||||
search_but->arg_free_fn = search_arg_free_fn;
|
||||
|
||||
if (search_exec_fn) {
|
||||
#ifdef DEBUG
|
||||
if (but->func) {
|
||||
if (search_but->but.func) {
|
||||
/* watch this, can be cause of much confusion, see: T47691 */
|
||||
printf("%s: warning, overwriting button callback with search function callback!\n",
|
||||
__func__);
|
||||
}
|
||||
#endif
|
||||
UI_but_func_set(but, search_exec_fn, search->arg, active);
|
||||
/* Handling will pass the active item as arg2 later, so keep it NULL here. */
|
||||
UI_but_func_set(but, search_exec_fn, search_but->arg, NULL);
|
||||
}
|
||||
|
||||
/* search buttons show red-alert if item doesn't exist, not for menus */
|
||||
if (0 == (but->block->flag & UI_BLOCK_LOOP)) {
|
||||
/* skip empty buttons, not all buttons need input, we only show invalid */
|
||||
if (but->drawstr[0]) {
|
||||
ui_but_search_refresh(but);
|
||||
ui_but_search_refresh(search_but);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn context_menu_fn)
|
||||
{
|
||||
struct uiButSearchData *search = but->search;
|
||||
search->context_menu_fn = context_menu_fn;
|
||||
uiButSearch *but_search = (uiButSearch *)but;
|
||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
||||
|
||||
but_search->item_context_menu_fn = context_menu_fn;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6441,14 +6563,18 @@ void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn co
|
||||
*/
|
||||
void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string)
|
||||
{
|
||||
struct uiButSearchData *search = but->search;
|
||||
search->sep_string = search_sep_string;
|
||||
uiButSearch *but_search = (uiButSearch *)but;
|
||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
||||
|
||||
but_search->item_sep_string = search_sep_string;
|
||||
}
|
||||
|
||||
void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn)
|
||||
{
|
||||
struct uiButSearchData *search = but->search;
|
||||
search->tooltip_fn = tooltip_fn;
|
||||
uiButSearch *but_search = (uiButSearch *)but;
|
||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
||||
|
||||
but_search->item_tooltip_fn = tooltip_fn;
|
||||
}
|
||||
|
||||
/* Callbacks for operator search button. */
|
||||
|
@@ -120,35 +120,41 @@ void ui_but_anim_flag(uiBut *but, const AnimationEvalContext *anim_eval_context)
|
||||
}
|
||||
}
|
||||
|
||||
static uiBut *ui_but_anim_decorate_find_attached_button(uiBut *but_decorate)
|
||||
static uiBut *ui_but_anim_decorate_find_attached_button(uiButDecorator *but_decorate)
|
||||
{
|
||||
uiBut *but_iter = NULL;
|
||||
|
||||
BLI_assert(UI_but_is_decorator(but_decorate));
|
||||
BLI_assert(but_decorate->rnasearchpoin.data && but_decorate->rnasearchprop);
|
||||
BLI_assert(UI_but_is_decorator(&but_decorate->but));
|
||||
BLI_assert(but_decorate->rnapoin.data && but_decorate->rnaprop);
|
||||
|
||||
LISTBASE_CIRCULAR_BACKWARD_BEGIN (&but_decorate->block->buttons, but_iter, but_decorate->prev) {
|
||||
if (but_iter != but_decorate &&
|
||||
ui_but_rna_equals_ex(but_iter,
|
||||
&but_decorate->rnasearchpoin,
|
||||
but_decorate->rnasearchprop,
|
||||
POINTER_AS_INT(but_decorate->custom_data))) {
|
||||
LISTBASE_CIRCULAR_BACKWARD_BEGIN (
|
||||
&but_decorate->but.block->buttons, but_iter, but_decorate->but.prev) {
|
||||
if (but_iter != (uiBut *)but_decorate &&
|
||||
ui_but_rna_equals_ex(
|
||||
but_iter, &but_decorate->rnapoin, but_decorate->rnaprop, but_decorate->rnaindex)) {
|
||||
return but_iter;
|
||||
}
|
||||
}
|
||||
LISTBASE_CIRCULAR_BACKWARD_END(&but_decorate->block->buttons, but_iter, but_decorate->prev);
|
||||
LISTBASE_CIRCULAR_BACKWARD_END(
|
||||
&but_decorate->but.block->buttons, but_iter, but_decorate->but.prev);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ui_but_anim_decorate_update_from_flag(uiBut *but)
|
||||
void ui_but_anim_decorate_update_from_flag(uiButDecorator *decorator_but)
|
||||
{
|
||||
const uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but);
|
||||
if (!decorator_but->rnapoin.data || !decorator_but->rnaprop) {
|
||||
/* Nothing to do. */
|
||||
return;
|
||||
}
|
||||
|
||||
const uiBut *but_anim = ui_but_anim_decorate_find_attached_button(decorator_but);
|
||||
uiBut *but = &decorator_but->but;
|
||||
|
||||
if (!but_anim) {
|
||||
printf("Could not find button with matching property to decorate (%s.%s)\n",
|
||||
RNA_struct_identifier(but->rnasearchpoin.type),
|
||||
RNA_property_identifier(but->rnasearchprop));
|
||||
RNA_struct_identifier(decorator_but->rnapoin.type),
|
||||
RNA_property_identifier(decorator_but->rnaprop));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -325,7 +331,7 @@ void ui_but_anim_paste_driver(bContext *C)
|
||||
void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy))
|
||||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
uiBut *but_decorate = arg_but;
|
||||
uiButDecorator *but_decorate = arg_but;
|
||||
uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but_decorate);
|
||||
|
||||
if (!but_anim) {
|
||||
@@ -333,7 +339,7 @@ void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy)
|
||||
}
|
||||
|
||||
/* FIXME(campbell), swapping active pointer is weak. */
|
||||
SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active);
|
||||
SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->but.active);
|
||||
wm->op_undo_depth++;
|
||||
|
||||
if (but_anim->flag & UI_BUT_DRIVEN) {
|
||||
@@ -357,6 +363,6 @@ void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy)
|
||||
WM_operator_properties_free(&props_ptr);
|
||||
}
|
||||
|
||||
SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active);
|
||||
SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->but.active);
|
||||
wm->op_undo_depth--;
|
||||
}
|
||||
|
@@ -962,7 +962,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
|
||||
const PropertyType prop_type = RNA_property_type(but->rnaprop);
|
||||
if (((prop_type == PROP_POINTER) ||
|
||||
(prop_type == PROP_STRING && but->type == UI_BTYPE_SEARCH_MENU &&
|
||||
but->search->update_fn == ui_rna_collection_search_update_fn)) &&
|
||||
((uiButSearch *)but)->items_update_fn == ui_rna_collection_search_update_fn)) &&
|
||||
ui_jump_to_target_button_poll(C)) {
|
||||
uiItemO(layout,
|
||||
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Jump to Target"),
|
||||
|
@@ -767,11 +767,12 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
|
||||
after->rnapoin = but->rnapoin;
|
||||
after->rnaprop = but->rnaprop;
|
||||
|
||||
if (but->search != NULL) {
|
||||
after->search_arg_free_fn = but->search->arg_free_fn;
|
||||
after->search_arg = but->search->arg;
|
||||
but->search->arg_free_fn = NULL;
|
||||
but->search->arg = NULL;
|
||||
if (but->type == UI_BTYPE_SEARCH_MENU) {
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
after->search_arg_free_fn = search_but->arg_free_fn;
|
||||
after->search_arg = search_but->arg;
|
||||
search_but->arg_free_fn = NULL;
|
||||
search_but->arg = NULL;
|
||||
}
|
||||
|
||||
if (but->context) {
|
||||
@@ -1047,8 +1048,19 @@ static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
|
||||
but->rename_orig = data->origstr;
|
||||
data->origstr = NULL;
|
||||
}
|
||||
|
||||
void *orig_arg2 = but->func_arg2;
|
||||
|
||||
/* If arg2 isn't in use already, pass the active search item through it. */
|
||||
if ((but->func_arg2 == NULL) && (but->type == UI_BTYPE_SEARCH_MENU)) {
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
but->func_arg2 = search_but->item_active;
|
||||
}
|
||||
|
||||
ui_apply_but_func(C, but);
|
||||
|
||||
but->func_arg2 = orig_arg2;
|
||||
|
||||
data->retval = but->retval;
|
||||
data->applied = true;
|
||||
}
|
||||
@@ -2087,6 +2099,7 @@ static void ui_apply_but(
|
||||
/* handle different types */
|
||||
switch (but->type) {
|
||||
case UI_BTYPE_BUT:
|
||||
case UI_BTYPE_DECORATOR:
|
||||
ui_apply_but_BUT(C, but, data);
|
||||
break;
|
||||
case UI_BTYPE_TEXT:
|
||||
@@ -3321,7 +3334,9 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
|
||||
|
||||
/* optional searchbox */
|
||||
if (but->type == UI_BTYPE_SEARCH_MENU) {
|
||||
data->searchbox = but->search->create_fn(C, data->region, but);
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
|
||||
data->searchbox = search_but->popup_create_fn(C, data->region, search_but);
|
||||
ui_searchbox_update(C, data->searchbox, but, true); /* true = reset */
|
||||
}
|
||||
|
||||
@@ -5698,21 +5713,24 @@ static bool ui_numedit_but_UNITVEC(
|
||||
return changed;
|
||||
}
|
||||
|
||||
static void ui_palette_set_active(uiBut *but)
|
||||
static void ui_palette_set_active(uiButColor *color_but)
|
||||
{
|
||||
if ((int)(but->a1) == UI_PALETTE_COLOR) {
|
||||
Palette *palette = (Palette *)but->rnapoin.owner_id;
|
||||
PaletteColor *color = but->rnapoin.data;
|
||||
if (color_but->is_pallete_color) {
|
||||
Palette *palette = (Palette *)color_but->but.rnapoin.owner_id;
|
||||
PaletteColor *color = color_but->but.rnapoin.data;
|
||||
palette->active_color = BLI_findindex(&palette->colors, color);
|
||||
}
|
||||
}
|
||||
|
||||
static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
|
||||
{
|
||||
BLI_assert(but->type == UI_BTYPE_COLOR);
|
||||
uiButColor *color_but = (uiButColor *)but;
|
||||
|
||||
if (data->state == BUTTON_STATE_HIGHLIGHT) {
|
||||
/* first handle click on icondrag type button */
|
||||
if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
|
||||
ui_palette_set_active(but);
|
||||
ui_palette_set_active(color_but);
|
||||
if (ui_but_contains_point_px_icon(but, data->region, event)) {
|
||||
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
|
||||
data->dragstartx = event->x;
|
||||
@@ -5722,7 +5740,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
|
||||
}
|
||||
#ifdef USE_DRAG_TOGGLE
|
||||
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
|
||||
ui_palette_set_active(but);
|
||||
ui_palette_set_active(color_but);
|
||||
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
|
||||
data->dragstartx = event->x;
|
||||
data->dragstarty = event->y;
|
||||
@@ -5731,7 +5749,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
|
||||
#endif
|
||||
/* regular open menu */
|
||||
if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) {
|
||||
ui_palette_set_active(but);
|
||||
ui_palette_set_active(color_but);
|
||||
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
|
||||
return WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
@@ -5762,8 +5780,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
|
||||
ui_apply_but(C, but->block, but, data, true);
|
||||
return WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
if ((int)(but->a1) == UI_PALETTE_COLOR && event->type == EVT_DELKEY &&
|
||||
event->val == KM_PRESS) {
|
||||
if (color_but->is_pallete_color && (event->type == EVT_DELKEY) && (event->val == KM_PRESS)) {
|
||||
Palette *palette = (Palette *)but->rnapoin.owner_id;
|
||||
PaletteColor *color = but->rnapoin.data;
|
||||
|
||||
@@ -5794,7 +5811,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
|
||||
}
|
||||
|
||||
if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
|
||||
if ((int)(but->a1) == UI_PALETTE_COLOR) {
|
||||
if (color_but->is_pallete_color) {
|
||||
if (!event->ctrl) {
|
||||
float color[3];
|
||||
Paint *paint = BKE_paint_get_active_from_context(C);
|
||||
@@ -7522,6 +7539,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
|
||||
|
||||
switch (but->type) {
|
||||
case UI_BTYPE_BUT:
|
||||
case UI_BTYPE_DECORATOR:
|
||||
retval = ui_do_but_BUT(C, but, data, event);
|
||||
break;
|
||||
case UI_BTYPE_KEY_EVENT:
|
||||
@@ -7597,13 +7615,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
|
||||
retval = ui_do_but_BUT(C, but, data, event);
|
||||
break;
|
||||
case UI_BTYPE_COLOR:
|
||||
if (but->a1 == -1) {
|
||||
/* signal to prevent calling up color picker */
|
||||
retval = ui_do_but_EXIT(C, but, data, event);
|
||||
}
|
||||
else {
|
||||
retval = ui_do_but_COLOR(C, but, data, event);
|
||||
}
|
||||
retval = ui_do_but_COLOR(C, but, data, event);
|
||||
break;
|
||||
case UI_BTYPE_UNITVEC:
|
||||
retval = ui_do_but_UNITVEC(C, block, but, data, event);
|
||||
@@ -8430,7 +8442,7 @@ void UI_context_update_anim_flag(const bContext *C)
|
||||
ui_but_anim_flag(but, &anim_eval_context);
|
||||
ui_but_override_flag(CTX_data_main(C), but);
|
||||
if (UI_but_is_decorator(but)) {
|
||||
ui_but_anim_decorate_update_from_flag(but);
|
||||
ui_but_anim_decorate_update_from_flag((uiButDecorator *)but);
|
||||
}
|
||||
|
||||
ED_region_tag_redraw(region);
|
||||
|
@@ -147,19 +147,11 @@ enum {
|
||||
/* max amount of items a radial menu (pie menu) can contain */
|
||||
#define PIE_MAX_ITEMS 8
|
||||
|
||||
struct uiButSearchData {
|
||||
uiButSearchCreateFn create_fn;
|
||||
uiButSearchUpdateFn update_fn;
|
||||
void *arg;
|
||||
uiButSearchArgFreeFn arg_free_fn;
|
||||
uiButSearchContextMenuFn context_menu_fn;
|
||||
uiButSearchTooltipFn tooltip_fn;
|
||||
|
||||
const char *sep_string;
|
||||
};
|
||||
|
||||
struct uiBut {
|
||||
struct uiBut *next, *prev;
|
||||
|
||||
/* Pointer back to the layout item holding this button. */
|
||||
uiLayout *layout;
|
||||
int flag, drawflag;
|
||||
eButType type;
|
||||
eButPointerType pointype;
|
||||
@@ -185,8 +177,6 @@ struct uiBut {
|
||||
* - UI_BTYPE_LABEL: Use `(a1 == 1.0f)` to use a2 as a blending factor (imaginative!).
|
||||
* - UI_BTYPE_SCROLL: Use as scroll size.
|
||||
* - UI_BTYPE_SEARCH_MENU: Use as number or rows.
|
||||
* - UI_BTYPE_COLOR: Use as indication of color palette.
|
||||
* - UI_BTYPE_PROGRESS_BAR: Use to store progress (0..1).
|
||||
*/
|
||||
float a1;
|
||||
|
||||
@@ -196,7 +186,6 @@ struct uiBut {
|
||||
* - UI_BTYPE_NUM: Use to store RNA 'precision' value, for dragging and click-step.
|
||||
* - UI_BTYPE_LABEL: If `(a1 == 1.0f)` use a2 as a blending factor.
|
||||
* - UI_BTYPE_SEARCH_MENU: Use as number or columns.
|
||||
* - UI_BTYPE_COLOR: Use as index in palette (not so good, needs refactor).
|
||||
*/
|
||||
float a2;
|
||||
|
||||
@@ -214,8 +203,6 @@ struct uiBut {
|
||||
uiButCompleteFunc autocomplete_func;
|
||||
void *autofunc_arg;
|
||||
|
||||
struct uiButSearchData *search;
|
||||
|
||||
uiButHandleRenameFunc rename_func;
|
||||
void *rename_arg1;
|
||||
void *rename_orig;
|
||||
@@ -256,9 +243,6 @@ struct uiBut {
|
||||
struct PropertyRNA *rnaprop;
|
||||
int rnaindex;
|
||||
|
||||
struct PointerRNA rnasearchpoin;
|
||||
struct PropertyRNA *rnasearchprop;
|
||||
|
||||
/* Operator data */
|
||||
struct wmOperatorType *optype;
|
||||
struct PointerRNA *opptr;
|
||||
@@ -294,11 +278,56 @@ struct uiBut {
|
||||
uiBlock *block;
|
||||
};
|
||||
|
||||
/** Derived struct for #UI_BTYPE_COLOR */
|
||||
typedef struct uiButColor {
|
||||
uiBut but;
|
||||
|
||||
bool is_pallete_color;
|
||||
int palette_color_index;
|
||||
} uiButColor;
|
||||
|
||||
/** Derived struct for #UI_BTYPE_TAB */
|
||||
typedef struct uiButTab {
|
||||
uiBut but;
|
||||
struct MenuType *menu;
|
||||
} uiButTab;
|
||||
|
||||
/** Derived struct for #UI_BTYPE_SEARCH_MENU */
|
||||
typedef struct uiButSearch {
|
||||
uiBut but;
|
||||
|
||||
uiButSearchCreateFn popup_create_fn;
|
||||
uiButSearchUpdateFn items_update_fn;
|
||||
void *item_active;
|
||||
|
||||
void *arg;
|
||||
uiButSearchArgFreeFn arg_free_fn;
|
||||
|
||||
uiButSearchContextMenuFn item_context_menu_fn;
|
||||
uiButSearchTooltipFn item_tooltip_fn;
|
||||
|
||||
const char *item_sep_string;
|
||||
|
||||
struct PointerRNA rnasearchpoin;
|
||||
struct PropertyRNA *rnasearchprop;
|
||||
} uiButSearch;
|
||||
|
||||
/** Derived struct for #UI_BTYPE_DECORATOR */
|
||||
typedef struct uiButDecorator {
|
||||
uiBut but;
|
||||
|
||||
struct PointerRNA rnapoin;
|
||||
struct PropertyRNA *rnaprop;
|
||||
int rnaindex;
|
||||
} uiButDecorator;
|
||||
|
||||
typedef struct uiButProgressbar {
|
||||
uiBut but;
|
||||
|
||||
/* 0..1 range */
|
||||
float progress;
|
||||
} uiButProgressbar;
|
||||
|
||||
/**
|
||||
* Additional, superimposed icon for a button, invoking an operator.
|
||||
*/
|
||||
@@ -493,6 +522,8 @@ extern void ui_window_to_region_rcti(const struct ARegion *region,
|
||||
extern void ui_region_to_window(const struct ARegion *region, int *x, int *y);
|
||||
extern void ui_region_winrct_get_no_margin(const struct ARegion *region, struct rcti *r_rect);
|
||||
|
||||
uiBut *ui_but_change_type(uiBut *but, eButType new_type);
|
||||
|
||||
extern double ui_but_value_get(uiBut *but);
|
||||
extern void ui_but_value_set(uiBut *but, double value);
|
||||
extern void ui_but_hsv_set(uiBut *but);
|
||||
@@ -662,13 +693,13 @@ ColorPicker *ui_block_colorpicker_create(struct uiBlock *block);
|
||||
/* Searchbox for string button */
|
||||
struct ARegion *ui_searchbox_create_generic(struct bContext *C,
|
||||
struct ARegion *butregion,
|
||||
uiBut *but);
|
||||
uiButSearch *search_but);
|
||||
struct ARegion *ui_searchbox_create_operator(struct bContext *C,
|
||||
struct ARegion *butregion,
|
||||
uiBut *but);
|
||||
uiButSearch *search_but);
|
||||
struct ARegion *ui_searchbox_create_menu(struct bContext *C,
|
||||
struct ARegion *butregion,
|
||||
uiBut *but);
|
||||
uiButSearch *search_but);
|
||||
|
||||
bool ui_searchbox_inside(struct ARegion *region, int x, int y);
|
||||
int ui_searchbox_find_index(struct ARegion *region, const char *name);
|
||||
@@ -681,7 +712,7 @@ bool ui_searchbox_event(struct bContext *C,
|
||||
const struct wmEvent *event);
|
||||
bool ui_searchbox_apply(uiBut *but, struct ARegion *region);
|
||||
void ui_searchbox_free(struct bContext *C, struct ARegion *region);
|
||||
void ui_but_search_refresh(uiBut *but);
|
||||
void ui_but_search_refresh(uiButSearch *but);
|
||||
|
||||
/* interface_region_menu_popup.c */
|
||||
int ui_but_menu_step(uiBut *but, int step);
|
||||
@@ -925,11 +956,12 @@ void ui_resources_free(void);
|
||||
|
||||
/* interface_layout.c */
|
||||
void ui_layout_add_but(uiLayout *layout, uiBut *but);
|
||||
void ui_but_add_search(uiBut *but,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
PointerRNA *searchptr,
|
||||
PropertyRNA *searchprop);
|
||||
bool ui_layout_replace_but_ptr(uiLayout *layout, const void *old_but_ptr, uiBut *new_but);
|
||||
uiBut *ui_but_add_search(uiBut *but,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
PointerRNA *searchptr,
|
||||
PropertyRNA *searchprop);
|
||||
void ui_layout_list_set_labels_active(uiLayout *layout);
|
||||
/* menu callback */
|
||||
void ui_item_menutype_func(struct bContext *C, struct uiLayout *layout, void *arg_mt);
|
||||
@@ -950,7 +982,7 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str);
|
||||
void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, float cfra);
|
||||
|
||||
void ui_but_anim_decorate_cb(struct bContext *C, void *arg_but, void *arg_dummy);
|
||||
void ui_but_anim_decorate_update_from_flag(uiBut *but);
|
||||
void ui_but_anim_decorate_update_from_flag(uiButDecorator *but);
|
||||
|
||||
/* interface_query.c */
|
||||
bool ui_but_is_editable(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
|
||||
|
@@ -2278,7 +2278,7 @@ void uiItemFullR(uiLayout *layout,
|
||||
/* property with separate label */
|
||||
else if (type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) {
|
||||
but = ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h, flag);
|
||||
ui_but_add_search(but, ptr, prop, NULL, NULL);
|
||||
but = ui_but_add_search(but, ptr, prop, NULL, NULL);
|
||||
|
||||
if (layout->redalert) {
|
||||
UI_but_flag_enable(but, UI_BUT_REDALERT);
|
||||
@@ -2651,7 +2651,10 @@ static void ui_rna_collection_search_arg_free_fn(void *ptr)
|
||||
MEM_freeN(ptr);
|
||||
}
|
||||
|
||||
void ui_but_add_search(
|
||||
/**
|
||||
* \note May reallocate \a but, so the possibly new address is returned.
|
||||
*/
|
||||
uiBut *ui_but_add_search(
|
||||
uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop)
|
||||
{
|
||||
StructRNA *ptype;
|
||||
@@ -2669,11 +2672,13 @@ void ui_but_add_search(
|
||||
/* turn button into search button */
|
||||
if (searchprop) {
|
||||
uiRNACollectionSearch *coll_search = MEM_mallocN(sizeof(*coll_search), __func__);
|
||||
uiButSearch *search_but;
|
||||
|
||||
but->type = UI_BTYPE_SEARCH_MENU;
|
||||
but = ui_but_change_type(but, UI_BTYPE_SEARCH_MENU);
|
||||
search_but = (uiButSearch *)but;
|
||||
search_but->rnasearchpoin = *searchptr;
|
||||
search_but->rnasearchprop = searchprop;
|
||||
but->hardmax = MAX2(but->hardmax, 256.0f);
|
||||
but->rnasearchpoin = *searchptr;
|
||||
but->rnasearchprop = searchprop;
|
||||
but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT;
|
||||
if (RNA_property_is_unlink(prop)) {
|
||||
but->flag |= UI_BUT_VALUE_CLEAR;
|
||||
@@ -2707,6 +2712,8 @@ void ui_but_add_search(
|
||||
* so other code might have already set but->type to search menu... */
|
||||
but->flag |= UI_BUT_DISABLED;
|
||||
}
|
||||
|
||||
return but;
|
||||
}
|
||||
|
||||
void uiItemPointerR_prop(uiLayout *layout,
|
||||
@@ -2939,29 +2946,28 @@ void uiItemMContents(uiLayout *layout, const char *menuname)
|
||||
void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index)
|
||||
{
|
||||
uiBlock *block = layout->root->block;
|
||||
uiBut *but = NULL;
|
||||
|
||||
uiLayout *col;
|
||||
|
||||
UI_block_layout_set_current(block, layout);
|
||||
col = uiLayoutColumn(layout, false);
|
||||
col->space = 0;
|
||||
col->emboss = UI_EMBOSS_NONE;
|
||||
|
||||
if (ELEM(NULL, ptr, prop) || !RNA_property_animateable(ptr, prop)) {
|
||||
but = uiDefIconBut(block,
|
||||
UI_BTYPE_BUT,
|
||||
0,
|
||||
ICON_BLANK1,
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
NULL,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
"");
|
||||
uiBut *but = uiDefIconBut(block,
|
||||
UI_BTYPE_DECORATOR,
|
||||
0,
|
||||
ICON_BLANK1,
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
NULL,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
"");
|
||||
but->flag |= UI_BUT_DISABLED;
|
||||
return;
|
||||
}
|
||||
@@ -2971,27 +2977,28 @@ void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop,
|
||||
|
||||
/* Loop for the array-case, but only do in case of an expanded array. */
|
||||
for (int i = 0; i < (is_expand ? RNA_property_array_length(ptr, prop) : 1); i++) {
|
||||
but = uiDefIconBut(block,
|
||||
UI_BTYPE_BUT,
|
||||
0,
|
||||
ICON_DOT,
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
NULL,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
TIP_("Animate property"));
|
||||
UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL);
|
||||
but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK;
|
||||
uiButDecorator *decorator_but = (uiButDecorator *)uiDefIconBut(block,
|
||||
UI_BTYPE_DECORATOR,
|
||||
0,
|
||||
ICON_DOT,
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
NULL,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
TIP_("Animate property"));
|
||||
|
||||
UI_but_func_set(&decorator_but->but, ui_but_anim_decorate_cb, decorator_but, NULL);
|
||||
decorator_but->but.flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK;
|
||||
/* Reusing RNA search members, setting actual RNA data has many side-effects. */
|
||||
but->rnasearchpoin = *ptr;
|
||||
but->rnasearchprop = prop;
|
||||
decorator_but->rnapoin = *ptr;
|
||||
decorator_but->rnaprop = prop;
|
||||
/* ui_def_but_rna() sets non-array buttons to have a RNA index of 0. */
|
||||
but->custom_data = POINTER_FROM_INT((!is_array || is_expand) ? i : index);
|
||||
decorator_but->rnaindex = (!is_array || is_expand) ? i : index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4819,8 +4826,6 @@ void ui_layout_list_set_labels_active(uiLayout *layout)
|
||||
|
||||
uiLayout *uiLayoutListBox(uiLayout *layout,
|
||||
uiList *ui_list,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
PointerRNA *actptr,
|
||||
PropertyRNA *actprop)
|
||||
{
|
||||
@@ -4829,8 +4834,6 @@ uiLayout *uiLayoutListBox(uiLayout *layout,
|
||||
|
||||
but->custom_data = ui_list;
|
||||
|
||||
but->rnasearchpoin = *ptr;
|
||||
but->rnasearchprop = prop;
|
||||
but->rnapoin = *actptr;
|
||||
but->rnaprop = actprop;
|
||||
|
||||
@@ -5407,6 +5410,7 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but)
|
||||
else {
|
||||
BLI_addtail(&layout->items, bitem);
|
||||
}
|
||||
but->layout = layout;
|
||||
|
||||
if (layout->context) {
|
||||
but->context = layout->context;
|
||||
@@ -5418,6 +5422,30 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but)
|
||||
}
|
||||
}
|
||||
|
||||
bool ui_layout_replace_but_ptr(uiLayout *layout, const void *old_but_ptr, uiBut *new_but)
|
||||
{
|
||||
ListBase *child_list = layout->child_items_layout ? &layout->child_items_layout->items :
|
||||
&layout->items;
|
||||
|
||||
LISTBASE_FOREACH (uiItem *, item, child_list) {
|
||||
if (item->type == ITEM_BUTTON) {
|
||||
uiButtonItem *bitem = (uiButtonItem *)item;
|
||||
|
||||
if (bitem->but == old_but_ptr) {
|
||||
bitem->but = new_but;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ui_layout_replace_but_ptr((uiLayout *)item, old_but_ptr, new_but)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void uiLayoutSetFixedSize(uiLayout *layout, bool fixed_size)
|
||||
{
|
||||
if (fixed_size) {
|
||||
|
@@ -1148,10 +1148,11 @@ static bool jump_to_target_button(bContext *C, bool poll)
|
||||
/* For string properties with prop_search, look up the search collection item. */
|
||||
if (type == PROP_STRING) {
|
||||
const uiBut *but = UI_context_active_but_get(C);
|
||||
const uiButSearch *search_but = (but->type == UI_BTYPE_SEARCH_MENU) ? (uiButSearch *)but :
|
||||
NULL;
|
||||
|
||||
if (but->type == UI_BTYPE_SEARCH_MENU && but->search &&
|
||||
but->search->update_fn == ui_rna_collection_search_update_fn) {
|
||||
uiRNACollectionSearch *coll_search = but->search->arg;
|
||||
if (search_but && search_but->items_update_fn == ui_rna_collection_search_update_fn) {
|
||||
uiRNACollectionSearch *coll_search = search_but->arg;
|
||||
|
||||
char str_buf[MAXBONENAME];
|
||||
char *str_ptr = RNA_property_string_get_alloc(&ptr, prop, str_buf, sizeof(str_buf), NULL);
|
||||
|
@@ -113,7 +113,7 @@ bool UI_but_is_utf8(const uiBut *but)
|
||||
#ifdef USE_UI_POPOVER_ONCE
|
||||
bool ui_but_is_popover_once_compat(const uiBut *but)
|
||||
{
|
||||
return ((but->type == UI_BTYPE_BUT) || ui_but_is_toggle(but));
|
||||
return (ELEM(but->type, UI_BTYPE_BUT, UI_BTYPE_DECORATOR) || ui_but_is_toggle(but));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -302,8 +302,11 @@ bool ui_searchbox_inside(ARegion *region, int x, int y)
|
||||
bool ui_searchbox_apply(uiBut *but, ARegion *region)
|
||||
{
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
|
||||
but->func_arg2 = NULL;
|
||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
||||
|
||||
search_but->item_active = NULL;
|
||||
|
||||
if (data->active != -1) {
|
||||
const char *name = data->items.names[data->active] +
|
||||
@@ -316,7 +319,7 @@ bool ui_searchbox_apply(uiBut *but, ARegion *region)
|
||||
|
||||
BLI_strncpy(but->editstr, name, name_sep ? (name_sep - name) + 1 : data->items.maxstrlen);
|
||||
|
||||
but->func_arg2 = data->items.pointers[data->active];
|
||||
search_but->item_active = data->items.pointers[data->active];
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -340,8 +343,13 @@ static struct ARegion *wm_searchbox_tooltip_init(struct bContext *C,
|
||||
|
||||
LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) {
|
||||
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
|
||||
if (but->search && but->search->tooltip_fn) {
|
||||
return but->search->tooltip_fn(C, region, but->search->arg, but->func_arg2);
|
||||
if (but->type != UI_BTYPE_SEARCH_MENU) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
if (search_but->item_tooltip_fn) {
|
||||
return search_but->item_tooltip_fn(C, region, search_but->arg, search_but->item_active);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -352,10 +360,13 @@ bool ui_searchbox_event(
|
||||
bContext *C, ARegion *region, uiBut *but, ARegion *butregion, const wmEvent *event)
|
||||
{
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
int type = event->type, val = event->val;
|
||||
bool handled = false;
|
||||
bool tooltip_timer_started = false;
|
||||
|
||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
||||
|
||||
if (type == MOUSEPAN) {
|
||||
ui_pan_to_scroll(event, &type, &val);
|
||||
}
|
||||
@@ -373,7 +384,7 @@ bool ui_searchbox_event(
|
||||
break;
|
||||
case RIGHTMOUSE:
|
||||
if (val) {
|
||||
if (but->search->context_menu_fn) {
|
||||
if (search_but->item_context_menu_fn) {
|
||||
if (data->active != -1) {
|
||||
/* Check the cursor is over the active element
|
||||
* (a little confusing if this isn't the case, although it does work). */
|
||||
@@ -383,7 +394,7 @@ bool ui_searchbox_event(
|
||||
&rect, event->x - region->winrct.xmin, event->y - region->winrct.ymin)) {
|
||||
|
||||
void *active = data->items.pointers[data->active];
|
||||
if (but->search->context_menu_fn(C, but->search->arg, active, event)) {
|
||||
if (search_but->item_context_menu_fn(C, search_but->arg, active, event)) {
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
@@ -417,7 +428,7 @@ bool ui_searchbox_event(
|
||||
if (is_inside) {
|
||||
if (data->active != -1) {
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
but->func_arg2 = data->items.pointers[data->active];
|
||||
search_but->item_active = data->items.pointers[data->active];
|
||||
WM_tooltip_timer_init(C, CTX_wm_window(C), area, butregion, wm_searchbox_tooltip_init);
|
||||
tooltip_timer_started = true;
|
||||
}
|
||||
@@ -437,18 +448,24 @@ bool ui_searchbox_event(
|
||||
}
|
||||
|
||||
/** Wrap #uiButSearchUpdateFn callback. */
|
||||
static void ui_searchbox_update_fn(bContext *C, uiBut *but, const char *str, uiSearchItems *items)
|
||||
static void ui_searchbox_update_fn(bContext *C,
|
||||
uiButSearch *search_but,
|
||||
const char *str,
|
||||
uiSearchItems *items)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
WM_tooltip_clear(C, win);
|
||||
but->search->update_fn(C, but->search->arg, str, items);
|
||||
search_but->items_update_fn(C, search_but->arg, str, items);
|
||||
}
|
||||
|
||||
/* region is the search box itself */
|
||||
void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool reset)
|
||||
{
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
|
||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
||||
|
||||
/* reset vars */
|
||||
data->items.totitem = 0;
|
||||
data->items.more = 0;
|
||||
@@ -460,9 +477,9 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re
|
||||
data->active = -1;
|
||||
|
||||
/* handle active */
|
||||
if (but->search->update_fn && but->func_arg2) {
|
||||
data->items.active = but->func_arg2;
|
||||
ui_searchbox_update_fn(C, but, but->editstr, &data->items);
|
||||
if (search_but->items_update_fn && search_but->item_active) {
|
||||
data->items.active = search_but->item_active;
|
||||
ui_searchbox_update_fn(C, search_but, but->editstr, &data->items);
|
||||
data->items.active = NULL;
|
||||
|
||||
/* found active item, calculate real offset by centering it */
|
||||
@@ -491,8 +508,8 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re
|
||||
}
|
||||
|
||||
/* callback */
|
||||
if (but->search->update_fn) {
|
||||
ui_searchbox_update_fn(C, but, but->editstr, &data->items);
|
||||
if (search_but->items_update_fn) {
|
||||
ui_searchbox_update_fn(C, search_but, but->editstr, &data->items);
|
||||
}
|
||||
|
||||
/* handle case where editstr is equal to one of items */
|
||||
@@ -523,13 +540,16 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re
|
||||
|
||||
int ui_searchbox_autocomplete(bContext *C, ARegion *region, uiBut *but, char *str)
|
||||
{
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
int match = AUTOCOMPLETE_NO_MATCH;
|
||||
|
||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
||||
|
||||
if (str[0]) {
|
||||
data->items.autocpl = UI_autocomplete_begin(str, ui_but_string_get_max_length(but));
|
||||
|
||||
ui_searchbox_update_fn(C, but, but->editstr, &data->items);
|
||||
ui_searchbox_update_fn(C, search_but, but->editstr, &data->items);
|
||||
|
||||
match = UI_autocomplete_end(data->items.autocpl, str);
|
||||
data->items.autocpl = NULL;
|
||||
@@ -673,10 +693,11 @@ static void ui_searchbox_region_free_cb(ARegion *region)
|
||||
region->regiondata = NULL;
|
||||
}
|
||||
|
||||
ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but)
|
||||
ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiButSearch *search_but)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
const uiStyle *style = UI_style_get();
|
||||
uiBut *but = &search_but->but;
|
||||
static ARegionType type;
|
||||
ARegion *region;
|
||||
uiSearchboxData *data;
|
||||
@@ -725,7 +746,7 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but
|
||||
if (but->optype != NULL || (but->drawflag & UI_BUT_HAS_SHORTCUT) != 0) {
|
||||
data->use_sep = true;
|
||||
}
|
||||
data->sep_string = but->search->sep_string;
|
||||
data->sep_string = search_but->item_sep_string;
|
||||
|
||||
/* compute position */
|
||||
if (but->block->flag & UI_BLOCK_SEARCH_MENU) {
|
||||
@@ -945,12 +966,12 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
|
||||
}
|
||||
}
|
||||
|
||||
ARegion *ui_searchbox_create_operator(bContext *C, ARegion *butregion, uiBut *but)
|
||||
ARegion *ui_searchbox_create_operator(bContext *C, ARegion *butregion, uiButSearch *search_but)
|
||||
{
|
||||
ARegion *region;
|
||||
|
||||
UI_but_drawflag_enable(but, UI_BUT_HAS_SHORTCUT);
|
||||
region = ui_searchbox_create_generic(C, butregion, but);
|
||||
UI_but_drawflag_enable(&search_but->but, UI_BUT_HAS_SHORTCUT);
|
||||
region = ui_searchbox_create_generic(C, butregion, search_but);
|
||||
|
||||
region->type->draw = ui_searchbox_region_draw_cb__operator;
|
||||
|
||||
@@ -967,12 +988,12 @@ static void ui_searchbox_region_draw_cb__menu(const bContext *UNUSED(C), ARegion
|
||||
/* Currently unused. */
|
||||
}
|
||||
|
||||
ARegion *ui_searchbox_create_menu(bContext *C, ARegion *butregion, uiBut *but)
|
||||
ARegion *ui_searchbox_create_menu(bContext *C, ARegion *butregion, uiButSearch *search_but)
|
||||
{
|
||||
ARegion *region;
|
||||
|
||||
UI_but_drawflag_enable(but, UI_BUT_HAS_SHORTCUT);
|
||||
region = ui_searchbox_create_generic(C, butregion, but);
|
||||
UI_but_drawflag_enable(&search_but->but, UI_BUT_HAS_SHORTCUT);
|
||||
region = ui_searchbox_create_generic(C, butregion, search_but);
|
||||
|
||||
if (false) {
|
||||
region->type->draw = ui_searchbox_region_draw_cb__menu;
|
||||
@@ -983,8 +1004,9 @@ ARegion *ui_searchbox_create_menu(bContext *C, ARegion *butregion, uiBut *but)
|
||||
|
||||
/* sets red alert if button holds a string it can't find */
|
||||
/* XXX weak: search_func adds all partial matches... */
|
||||
void ui_but_search_refresh(uiBut *but)
|
||||
void ui_but_search_refresh(uiButSearch *search_but)
|
||||
{
|
||||
uiBut *but = &search_but->but;
|
||||
uiSearchItems *items;
|
||||
int x1;
|
||||
|
||||
@@ -1004,7 +1026,7 @@ void ui_but_search_refresh(uiBut *but)
|
||||
items->names[x1] = MEM_callocN(but->hardmax + 1, "search names");
|
||||
}
|
||||
|
||||
ui_searchbox_update_fn(but->block->evil_C, but, but->drawstr, items);
|
||||
ui_searchbox_update_fn(but->block->evil_C, search_but, but->drawstr, items);
|
||||
|
||||
/* only redalert when we are sure of it, this can miss cases when >10 matches */
|
||||
if (items->totitem == 0) {
|
||||
|
@@ -5512,22 +5512,24 @@ void uiTemplatePalette(uiLayout *layout,
|
||||
}
|
||||
|
||||
RNA_pointer_create(&palette->id, &RNA_PaletteColor, color, &color_ptr);
|
||||
uiDefButR(block,
|
||||
UI_BTYPE_COLOR,
|
||||
0,
|
||||
"",
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
&color_ptr,
|
||||
"color",
|
||||
-1,
|
||||
0.0,
|
||||
1.0,
|
||||
UI_PALETTE_COLOR,
|
||||
col_id,
|
||||
"");
|
||||
uiButColor *color_but = (uiButColor *)uiDefButR(block,
|
||||
UI_BTYPE_COLOR,
|
||||
0,
|
||||
"",
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
&color_ptr,
|
||||
"color",
|
||||
-1,
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
"");
|
||||
color_but->is_pallete_color = true;
|
||||
color_but->palette_color_index = col_id;
|
||||
row_cols++;
|
||||
col_id++;
|
||||
}
|
||||
@@ -6210,7 +6212,7 @@ void uiTemplateList(uiLayout *layout,
|
||||
switch (layout_type) {
|
||||
case UILST_LAYOUT_DEFAULT:
|
||||
/* layout */
|
||||
box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
|
||||
box = uiLayoutListBox(layout, ui_list, active_dataptr, activeprop);
|
||||
glob = uiLayoutColumn(box, true);
|
||||
row = uiLayoutRow(glob, false);
|
||||
col = uiLayoutColumn(row, true);
|
||||
@@ -6348,7 +6350,7 @@ void uiTemplateList(uiLayout *layout,
|
||||
}
|
||||
break;
|
||||
case UILST_LAYOUT_GRID:
|
||||
box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
|
||||
box = uiLayoutListBox(layout, ui_list, active_dataptr, activeprop);
|
||||
glob = uiLayoutColumn(box, true);
|
||||
row = uiLayoutRow(glob, false);
|
||||
col = uiLayoutColumn(row, true);
|
||||
@@ -6789,22 +6791,24 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
|
||||
struct ProgressTooltip_Store *tip_arg = MEM_mallocN(sizeof(*tip_arg), __func__);
|
||||
tip_arg->wm = wm;
|
||||
tip_arg->owner = owner;
|
||||
uiBut *but_progress = uiDefIconTextBut(block,
|
||||
UI_BTYPE_PROGRESS_BAR,
|
||||
0,
|
||||
0,
|
||||
text,
|
||||
UI_UNIT_X,
|
||||
0,
|
||||
UI_UNIT_X * 6.0f,
|
||||
UI_UNIT_Y,
|
||||
NULL,
|
||||
0.0f,
|
||||
0.0f,
|
||||
progress,
|
||||
0,
|
||||
NULL);
|
||||
UI_but_func_tooltip_set(but_progress, progress_tooltip_func, tip_arg);
|
||||
uiButProgressbar *but_progress = (uiButProgressbar *)uiDefIconTextBut(block,
|
||||
UI_BTYPE_PROGRESS_BAR,
|
||||
0,
|
||||
0,
|
||||
text,
|
||||
UI_UNIT_X,
|
||||
0,
|
||||
UI_UNIT_X * 6.0f,
|
||||
UI_UNIT_Y,
|
||||
NULL,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
but_progress->progress = progress;
|
||||
UI_but_func_tooltip_set(&but_progress->but, progress_tooltip_func, tip_arg);
|
||||
}
|
||||
|
||||
if (!wm->is_interface_locked) {
|
||||
|
@@ -148,7 +148,7 @@ uiBut *uiDefAutoButR(uiBlock *block,
|
||||
if (RNA_property_array_check(prop) && index == -1) {
|
||||
if (ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA)) {
|
||||
but = uiDefButR_prop(
|
||||
block, UI_BTYPE_COLOR, 0, name, x1, y1, x2, y2, ptr, prop, -1, 0, 0, -1, -1, NULL);
|
||||
block, UI_BTYPE_COLOR, 0, name, x1, y1, x2, y2, ptr, prop, -1, 0, 0, 0, 0, NULL);
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
|
@@ -1400,7 +1400,7 @@ static void widget_draw_icon(
|
||||
alpha *= but->a2;
|
||||
}
|
||||
}
|
||||
else if (ELEM(but->type, UI_BTYPE_BUT)) {
|
||||
else if (ELEM(but->type, UI_BTYPE_BUT, UI_BTYPE_DECORATOR)) {
|
||||
if (but->flag & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
|
||||
alpha *= 0.5f;
|
||||
}
|
||||
@@ -3609,6 +3609,7 @@ static void widget_scroll(
|
||||
static void widget_progressbar(
|
||||
uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
|
||||
{
|
||||
uiButProgressbar *but_progressbar = (uiButProgressbar *)but;
|
||||
uiWidgetBase wtb, wtb_bar;
|
||||
rcti rect_prog = *rect, rect_bar = *rect;
|
||||
|
||||
@@ -3616,7 +3617,7 @@ static void widget_progressbar(
|
||||
widget_init(&wtb_bar);
|
||||
|
||||
/* round corners */
|
||||
float value = but->a1;
|
||||
float value = but_progressbar->progress;
|
||||
float offs = wcol->roundness * BLI_rcti_size_y(&rect_prog);
|
||||
float w = value * BLI_rcti_size_x(&rect_prog);
|
||||
|
||||
@@ -3768,6 +3769,8 @@ static void widget_numslider(
|
||||
static void widget_swatch(
|
||||
uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
|
||||
{
|
||||
BLI_assert(but->type == UI_BTYPE_COLOR);
|
||||
uiButColor *color_but = (uiButColor *)but;
|
||||
uiWidgetBase wtb;
|
||||
float rad, col[4];
|
||||
|
||||
@@ -3822,8 +3825,8 @@ static void widget_swatch(
|
||||
}
|
||||
|
||||
widgetbase_draw_ex(&wtb, wcol, show_alpha_checkers);
|
||||
if (but->a1 == UI_PALETTE_COLOR &&
|
||||
((Palette *)but->rnapoin.owner_id)->active_color == (int)but->a2) {
|
||||
if (color_but->is_pallete_color &&
|
||||
((Palette *)but->rnapoin.owner_id)->active_color == color_but->palette_color_index) {
|
||||
float width = rect->xmax - rect->xmin;
|
||||
float height = rect->ymax - rect->ymin;
|
||||
/* find color luminance and change it slightly */
|
||||
@@ -4552,6 +4555,7 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu
|
||||
break;
|
||||
|
||||
case UI_BTYPE_BUT:
|
||||
case UI_BTYPE_DECORATOR:
|
||||
#ifdef USE_UI_TOOLBAR_HACK
|
||||
if ((but->icon != ICON_NONE) && UI_but_is_tool(but)) {
|
||||
wt = widget_type(UI_WTYPE_TOOLBAR_ITEM);
|
||||
|
Reference in New Issue
Block a user