Fix T62016: Outliner visibility icons drag behaviour broken
We are mixing bool and fancy 3-in-1 func-set buttons in the outliner. So they would return different pushed state in ui_drag_toggle_but_pushed_state(). We now have a callback function that allows the button to set its own pushed_button_state callback function. Note: This is a bit of overkill since we are planning to change the 3-in-1 outliner buttons. That said, it may be nice to have, since in the future we can mix those buttons for other things. Reviewers: brecht Differential Revision: https://developer.blender.org/D4434
This commit is contained in:
		@@ -438,6 +438,7 @@ typedef struct ARegion *(*uiButSearchCreateFunc)(struct bContext *C, struct AReg
 | 
			
		||||
typedef void (*uiButSearchFunc)(const struct bContext *C, void *arg, const char *str, uiSearchItems *items);
 | 
			
		||||
/* Must return allocated string. */
 | 
			
		||||
typedef char *(*uiButToolTipFunc)(struct bContext *C, void *argN, const char *tip);
 | 
			
		||||
typedef int (*uiButPushedStateFunc)(struct bContext *C, void *arg);
 | 
			
		||||
 | 
			
		||||
typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event);
 | 
			
		||||
 | 
			
		||||
@@ -880,6 +881,8 @@ void UI_but_focus_on_enter_event(struct wmWindow *win, uiBut *but);
 | 
			
		||||
 | 
			
		||||
void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN);
 | 
			
		||||
 | 
			
		||||
void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, void *arg);
 | 
			
		||||
 | 
			
		||||
/* Autocomplete
 | 
			
		||||
 *
 | 
			
		||||
 * Tab complete helper functions, for use in uiButCompleteFunc callbacks.
 | 
			
		||||
 
 | 
			
		||||
@@ -4456,6 +4456,12 @@ void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *argN)
 | 
			
		||||
	but->tip_argN = argN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	but->pushed_state_func = func;
 | 
			
		||||
	but->pushed_state_arg = arg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uiBut *uiDefBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip)
 | 
			
		||||
{
 | 
			
		||||
	uiBut *but = ui_def_but(block, UI_BTYPE_BLOCK, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
 | 
			
		||||
 
 | 
			
		||||
@@ -1240,13 +1240,18 @@ static bool ui_drag_toggle_but_is_supported(const uiBut *but)
 | 
			
		||||
 | 
			
		||||
/* Button pushed state to compare if other buttons match. Can be more
 | 
			
		||||
 * then just true or false for toggle buttons with more than 2 states. */
 | 
			
		||||
static int ui_drag_toggle_but_pushed_state(uiBut *but)
 | 
			
		||||
static int ui_drag_toggle_but_pushed_state(bContext *C, uiBut *but)
 | 
			
		||||
{
 | 
			
		||||
	if (but->rnapoin.data == NULL && but->poin == NULL && but->icon) {
 | 
			
		||||
		/* Assume icon identifies a unique state, for buttons that
 | 
			
		||||
		 * work though functions callbacks and don't have an boolean
 | 
			
		||||
		 * value that indicates the state. */
 | 
			
		||||
		return but->icon + but->iconadd;
 | 
			
		||||
		if (but->pushed_state_func) {
 | 
			
		||||
			return but->pushed_state_func(C, but->pushed_state_arg);
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			/* Assume icon identifies a unique state, for buttons that
 | 
			
		||||
			* work though functions callbacks and don't have an boolean
 | 
			
		||||
			* value that indicates the state. */
 | 
			
		||||
			return but->icon + but->iconadd;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else if (ui_but_is_bool(but)) {
 | 
			
		||||
		return ui_but_is_pushed(but);
 | 
			
		||||
@@ -1295,7 +1300,7 @@ static bool ui_drag_toggle_set_xy_xy(
 | 
			
		||||
					/* execute the button */
 | 
			
		||||
					if (ui_drag_toggle_but_is_supported(but)) {
 | 
			
		||||
						/* is it pressed? */
 | 
			
		||||
						int pushed_state_but = ui_drag_toggle_but_pushed_state(but);
 | 
			
		||||
						int pushed_state_but = ui_drag_toggle_but_pushed_state(C, but);
 | 
			
		||||
						if (pushed_state_but != pushed_state) {
 | 
			
		||||
							UI_but_execute(C, but);
 | 
			
		||||
							if (do_check) {
 | 
			
		||||
@@ -1754,7 +1759,7 @@ static bool ui_but_drag_init(
 | 
			
		||||
			 * typically 'button_activate_exit()' handles this */
 | 
			
		||||
			ui_apply_but_autokey(C, but);
 | 
			
		||||
 | 
			
		||||
			drag_info->pushed_state = ui_drag_toggle_but_pushed_state(but);
 | 
			
		||||
			drag_info->pushed_state = ui_drag_toggle_but_pushed_state(C, but);
 | 
			
		||||
			drag_info->but_cent_start[0] = BLI_rctf_cent_x(&but->rect);
 | 
			
		||||
			drag_info->but_cent_start[1] = BLI_rctf_cent_y(&but->rect);
 | 
			
		||||
			copy_v2_v2_int(drag_info->xy_init, &event->x);
 | 
			
		||||
 
 | 
			
		||||
@@ -320,6 +320,9 @@ struct uiBut {
 | 
			
		||||
	void *editcoba;
 | 
			
		||||
	void *editcumap;
 | 
			
		||||
 | 
			
		||||
	uiButPushedStateFunc pushed_state_func;
 | 
			
		||||
	void *pushed_state_arg;
 | 
			
		||||
 | 
			
		||||
	/* pointer back */
 | 
			
		||||
	uiBlock *block;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -268,6 +268,16 @@ static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int base_pushed_state_cb(bContext *UNUSED(C), void *poin, void *UNUSED(poin2))
 | 
			
		||||
{
 | 
			
		||||
	Base *base = poin;
 | 
			
		||||
	Object *ob = base->object;
 | 
			
		||||
 | 
			
		||||
	const bool is_visible = ((base->flag & BASE_HIDDEN) == 0) &&
 | 
			
		||||
	                        ((ob->restrictflag & OB_RESTRICT_VIEW) == 0);
 | 
			
		||||
	return !is_visible;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hidebutton_base_flag_cb(bContext *C, void *poin, void *poin2)
 | 
			
		||||
{
 | 
			
		||||
	wmWindow *win = CTX_wm_window(C);
 | 
			
		||||
@@ -333,6 +343,16 @@ static void hidebutton_base_flag_cb(bContext *C, void *poin, void *poin2)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int layer_collection_pushed_state_cb(bContext *UNUSED(C), void *poin, void *UNUSED(poin2))
 | 
			
		||||
{
 | 
			
		||||
	LayerCollection *lc = poin;
 | 
			
		||||
	Collection *collection = lc->collection;
 | 
			
		||||
 | 
			
		||||
	const bool is_visible = ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) == 0) &&
 | 
			
		||||
	                        ((collection->flag & COLLECTION_RESTRICT_VIEW) == 0);
 | 
			
		||||
	return !is_visible;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hidebutton_layer_collection_flag_cb(bContext *C, void *poin, void *poin2)
 | 
			
		||||
{
 | 
			
		||||
	wmWindow *win = CTX_wm_window(C);
 | 
			
		||||
@@ -602,6 +622,7 @@ static void outliner_draw_restrictbuts(
 | 
			
		||||
					             "* Alt to disable for all viewports\n"
 | 
			
		||||
					             "* Ctrl to isolate visibility"));
 | 
			
		||||
					UI_but_func_set(bt, hidebutton_base_flag_cb, view_layer, base);
 | 
			
		||||
					UI_but_func_pushed_state_set(bt, base_pushed_state_cb, base);
 | 
			
		||||
					UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
@@ -731,6 +752,7 @@ static void outliner_draw_restrictbuts(
 | 
			
		||||
						             "* Ctrl to isolate visibility\n"
 | 
			
		||||
						             "* Shift to hide inside objects and collections"));
 | 
			
		||||
						UI_but_func_set(bt, hidebutton_layer_collection_flag_cb, view_layer, lc);
 | 
			
		||||
						UI_but_func_pushed_state_set(bt, layer_collection_pushed_state_cb, lc);
 | 
			
		||||
						UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
 | 
			
		||||
					}
 | 
			
		||||
					else {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user