Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/interface/interface_handlers.c
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
| Show First 20 Lines • Show All 868 Lines • ▼ Show 20 Lines | if (buf) { | ||||
| WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, NULL); | WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, NULL); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void ui_apply_but_funcs_after(bContext *C) | static void ui_apply_but_funcs_after(bContext *C) | ||||
| { | { | ||||
| uiAfterFunc *afterf, after; | uiAfterFunc after; | ||||
| PointerRNA opptr; | PointerRNA opptr; | ||||
| ListBase funcs; | ListBase funcs; | ||||
| /* copy to avoid recursive calls */ | /* copy to avoid recursive calls */ | ||||
| funcs = UIAfterFuncs; | funcs = UIAfterFuncs; | ||||
| BLI_listbase_clear(&UIAfterFuncs); | BLI_listbase_clear(&UIAfterFuncs); | ||||
| for (afterf = funcs.first; afterf; afterf = after.next) { | LISTBASE_FOREACH_MUTABLE (uiAfterFunc *, afterf, &funcs) { | ||||
| after = *afterf; /* copy to avoid memleak on exit() */ | after = *afterf; /* copy to avoid memleak on exit() */ | ||||
| BLI_freelinkN(&funcs, afterf); | BLI_freelinkN(&funcs, afterf); | ||||
| if (after.context) { | if (after.context) { | ||||
| CTX_store_set(C, after.context); | CTX_store_set(C, after.context); | ||||
| } | } | ||||
| if (after.popup_op) { | if (after.popup_op) { | ||||
| ▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data) | ||||
| ui_apply_but_func(C, but); | ui_apply_but_func(C, but); | ||||
| data->retval = but->retval; | data->retval = but->retval; | ||||
| data->applied = true; | data->applied = true; | ||||
| } | } | ||||
| static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data) | static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data) | ||||
| { | { | ||||
| uiBut *bt; | |||||
| ui_but_value_set(but, but->hardmax); | ui_but_value_set(but, but->hardmax); | ||||
| ui_apply_but_func(C, but); | ui_apply_but_func(C, but); | ||||
| /* states of other row buttons */ | /* states of other row buttons */ | ||||
| for (bt = block->buttons.first; bt; bt = bt->next) { | LISTBASE_FOREACH (uiBut *, bt, &block->buttons) { | ||||
| if (bt != but && bt->poin == but->poin && ELEM(bt->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) { | if (bt != but && bt->poin == but->poin && ELEM(bt->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) { | ||||
| ui_but_update_edited(bt); | ui_but_update_edited(bt); | ||||
| } | } | ||||
| } | } | ||||
| data->retval = but->retval; | data->retval = but->retval; | ||||
| data->applied = true; | data->applied = true; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 147 Lines • ▼ Show 20 Lines | for (l = data->multi_data.mbuts; l; l = l->next) { | ||||
| } | } | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static void ui_multibut_restore(bContext *C, uiHandleButtonData *data, uiBlock *block) | static void ui_multibut_restore(bContext *C, uiHandleButtonData *data, uiBlock *block) | ||||
| { | { | ||||
| uiBut *but; | LISTBASE_FOREACH (uiBut *, but, &block->buttons) { | ||||
| for (but = block->buttons.first; but; but = but->next) { | |||||
| if (but->flag & UI_BUT_DRAG_MULTI) { | if (but->flag & UI_BUT_DRAG_MULTI) { | ||||
| uiButMultiState *mbut_state = ui_multibut_lookup(data, but); | uiButMultiState *mbut_state = ui_multibut_lookup(data, but); | ||||
| if (mbut_state) { | if (mbut_state) { | ||||
| ui_but_value_set(but, mbut_state->origvalue); | ui_but_value_set(but, mbut_state->origvalue); | ||||
| # ifdef USE_ALLSELECT | # ifdef USE_ALLSELECT | ||||
| if (mbut_state->select_others.elems_len > 0) { | if (mbut_state->select_others.elems_len > 0) { | ||||
| ui_selectcontext_apply( | ui_selectcontext_apply( | ||||
| Show All 36 Lines | if (data->multi_data.bs_mbuts) { | ||||
| data->multi_data.bs_mbuts = NULL; | data->multi_data.bs_mbuts = NULL; | ||||
| } | } | ||||
| } | } | ||||
| static bool ui_multibut_states_tag(uiBut *but_active, | static bool ui_multibut_states_tag(uiBut *but_active, | ||||
| uiHandleButtonData *data, | uiHandleButtonData *data, | ||||
| const wmEvent *event) | const wmEvent *event) | ||||
| { | { | ||||
| uiBut *but; | |||||
| float seg[2][2]; | float seg[2][2]; | ||||
| bool changed = false; | bool changed = false; | ||||
| seg[0][0] = data->multi_data.drag_start[0]; | seg[0][0] = data->multi_data.drag_start[0]; | ||||
| seg[0][1] = data->multi_data.drag_start[1]; | seg[0][1] = data->multi_data.drag_start[1]; | ||||
| seg[1][0] = event->x; | seg[1][0] = event->x; | ||||
| seg[1][1] = event->y; | seg[1][1] = event->y; | ||||
| BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_SETUP); | BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_SETUP); | ||||
| ui_window_to_block_fl(data->region, but_active->block, &seg[0][0], &seg[0][1]); | ui_window_to_block_fl(data->region, but_active->block, &seg[0][0], &seg[0][1]); | ||||
| ui_window_to_block_fl(data->region, but_active->block, &seg[1][0], &seg[1][1]); | ui_window_to_block_fl(data->region, but_active->block, &seg[1][0], &seg[1][1]); | ||||
| data->multi_data.has_mbuts = false; | data->multi_data.has_mbuts = false; | ||||
| /* follow ui_but_find_mouse_over_ex logic */ | /* follow ui_but_find_mouse_over_ex logic */ | ||||
| for (but = but_active->block->buttons.first; but; but = but->next) { | LISTBASE_FOREACH (uiBut *, but, &but_active->block->buttons) { | ||||
| bool drag_prev = false; | bool drag_prev = false; | ||||
| bool drag_curr = false; | bool drag_curr = false; | ||||
| /* re-set each time */ | /* re-set each time */ | ||||
| if (but->flag & UI_BUT_DRAG_MULTI) { | if (but->flag & UI_BUT_DRAG_MULTI) { | ||||
| but->flag &= ~UI_BUT_DRAG_MULTI; | but->flag &= ~UI_BUT_DRAG_MULTI; | ||||
| drag_prev = true; | drag_prev = true; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBlock *block) | static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBlock *block) | ||||
| { | { | ||||
| ARegion *region = data->region; | ARegion *region = data->region; | ||||
| const double value_delta = data->value - data->origvalue; | const double value_delta = data->value - data->origvalue; | ||||
| const double value_scale = data->multi_data.is_proportional ? (data->value / data->origvalue) : | const double value_scale = data->multi_data.is_proportional ? (data->value / data->origvalue) : | ||||
| 0.0; | 0.0; | ||||
| uiBut *but; | |||||
| BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_ENABLE); | BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_ENABLE); | ||||
| BLI_assert(data->multi_data.skip == false); | BLI_assert(data->multi_data.skip == false); | ||||
| for (but = block->buttons.first; but; but = but->next) { | LISTBASE_FOREACH (uiBut *, but, &block->buttons) { | ||||
| if (but->flag & UI_BUT_DRAG_MULTI) { | if (but->flag & UI_BUT_DRAG_MULTI) { | ||||
| /* mbut_states for delta */ | /* mbut_states for delta */ | ||||
| uiButMultiState *mbut_state = ui_multibut_lookup(data, but); | uiButMultiState *mbut_state = ui_multibut_lookup(data, but); | ||||
| if (mbut_state) { | if (mbut_state) { | ||||
| void *active_back; | void *active_back; | ||||
| ui_but_execute_begin(C, region, but, &active_back); | ui_but_execute_begin(C, region, but, &active_back); | ||||
| ▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | |||||
| } uiDragToggleHandle; | } uiDragToggleHandle; | ||||
| static bool ui_drag_toggle_set_xy_xy( | static bool ui_drag_toggle_set_xy_xy( | ||||
| bContext *C, ARegion *region, const int pushed_state, const int xy_src[2], const int xy_dst[2]) | bContext *C, ARegion *region, const int pushed_state, const int xy_src[2], const int xy_dst[2]) | ||||
| { | { | ||||
| /* popups such as layers won't re-evaluate on redraw */ | /* popups such as layers won't re-evaluate on redraw */ | ||||
| const bool do_check = (region->regiontype == RGN_TYPE_TEMPORARY); | const bool do_check = (region->regiontype == RGN_TYPE_TEMPORARY); | ||||
| bool changed = false; | bool changed = false; | ||||
| uiBlock *block; | |||||
| for (block = region->uiblocks.first; block; block = block->next) { | |||||
| uiBut *but; | |||||
| LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { | |||||
| float xy_a_block[2] = {UNPACK2(xy_src)}; | float xy_a_block[2] = {UNPACK2(xy_src)}; | ||||
| float xy_b_block[2] = {UNPACK2(xy_dst)}; | float xy_b_block[2] = {UNPACK2(xy_dst)}; | ||||
| ui_window_to_block_fl(region, block, &xy_a_block[0], &xy_a_block[1]); | ui_window_to_block_fl(region, block, &xy_a_block[0], &xy_a_block[1]); | ||||
| ui_window_to_block_fl(region, block, &xy_b_block[0], &xy_b_block[1]); | ui_window_to_block_fl(region, block, &xy_b_block[0], &xy_b_block[1]); | ||||
| for (but = block->buttons.first; but; but = but->next) { | LISTBASE_FOREACH (uiBut *, but, &block->buttons) { | ||||
| /* Note: ctrl is always true here because (at least for now) | /* Note: ctrl is always true here because (at least for now) | ||||
| * we always want to consider text control in this case, even when not embossed. */ | * we always want to consider text control in this case, even when not embossed. */ | ||||
| if (ui_but_is_interactive(but, true)) { | if (ui_but_is_interactive(but, true)) { | ||||
| if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) { | if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) { | ||||
| /* execute the button */ | /* execute the button */ | ||||
| if (ui_drag_toggle_but_is_supported(but)) { | if (ui_drag_toggle_but_is_supported(but)) { | ||||
| /* is it pressed? */ | /* is it pressed? */ | ||||
| ▲ Show 20 Lines • Show All 771 Lines • ▼ Show 20 Lines | |||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Button Drop Event | /** \name Button Drop Event | ||||
| * \{ */ | * \{ */ | ||||
| /* only call if event type is EVT_DROP */ | /* only call if event type is EVT_DROP */ | ||||
| static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleButtonData *data) | static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleButtonData *data) | ||||
| { | { | ||||
| wmDrag *wmd; | |||||
| ListBase *drags = event->customdata; /* drop event type has listbase customdata by default */ | ListBase *drags = event->customdata; /* drop event type has listbase customdata by default */ | ||||
| for (wmd = drags->first; wmd; wmd = wmd->next) { | LISTBASE_FOREACH (wmDrag *, wmd, drags) { | ||||
| if (wmd->type == WM_DRAG_ID) { | if (wmd->type == WM_DRAG_ID) { | ||||
| /* align these types with UI_but_active_drop_name */ | /* align these types with UI_but_active_drop_name */ | ||||
| if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { | if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { | ||||
| ID *id = WM_drag_ID(wmd, 0); | ID *id = WM_drag_ID(wmd, 0); | ||||
| button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); | button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); | ||||
| ui_textedit_string_set(but, data, id->name + 2); | ui_textedit_string_set(but, data, id->name + 2); | ||||
| ▲ Show 20 Lines • Show All 1,912 Lines • ▼ Show 20 Lines | static uiButExtraOpIcon *ui_but_extra_operator_icon_mouse_over_get(uiBut *but, | ||||
| int x = event->x, y = event->y; | int x = event->x, y = event->y; | ||||
| ui_window_to_block(data->region, but->block, &x, &y); | ui_window_to_block(data->region, but->block, &x, &y); | ||||
| if (!BLI_rctf_isect_pt(&but->rect, x, y)) { | if (!BLI_rctf_isect_pt(&but->rect, x, y)) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* Inverse order, from right to left. */ | /* Inverse order, from right to left. */ | ||||
| for (uiButExtraOpIcon *op_icon = but->extra_op_icons.last; op_icon; op_icon = op_icon->prev) { | LISTBASE_FOREACH_BACKWARD (uiButExtraOpIcon *, op_icon, &but->extra_op_icons) { | ||||
| if ((x > (xmax - icon_size)) && x < xmax) { | if ((x > (xmax - icon_size)) && x < xmax) { | ||||
| return op_icon; | return op_icon; | ||||
| } | } | ||||
| xmax -= icon_size; | xmax -= icon_size; | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 3,582 Lines • ▼ Show 20 Lines | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Button Tool Tip | /** \name Button Tool Tip | ||||
| * \{ */ | * \{ */ | ||||
| static void ui_blocks_set_tooltips(ARegion *region, const bool enable) | static void ui_blocks_set_tooltips(ARegion *region, const bool enable) | ||||
| { | { | ||||
| uiBlock *block; | |||||
| if (!region) { | if (!region) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* we disabled buttons when when they were already shown, and | /* we disabled buttons when when they were already shown, and | ||||
| * re-enable them on mouse move */ | * re-enable them on mouse move */ | ||||
| for (block = region->uiblocks.first; block; block = block->next) { | LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { | ||||
| block->tooltipdisabled = !enable; | block->tooltipdisabled = !enable; | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Recreate tooltip (use to update dynamic tips) | * Recreate tooltip (use to update dynamic tips) | ||||
| */ | */ | ||||
| void UI_but_tooltip_refresh(bContext *C, uiBut *but) | void UI_but_tooltip_refresh(bContext *C, uiBut *but) | ||||
| ▲ Show 20 Lines • Show All 362 Lines • ▼ Show 20 Lines | #endif | ||||
| } | } | ||||
| } | } | ||||
| static void button_activate_exit( | static void button_activate_exit( | ||||
| bContext *C, uiBut *but, uiHandleButtonData *data, const bool mousemove, const bool onfree) | bContext *C, uiBut *but, uiHandleButtonData *data, const bool mousemove, const bool onfree) | ||||
| { | { | ||||
| wmWindow *win = data->window; | wmWindow *win = data->window; | ||||
| uiBlock *block = but->block; | uiBlock *block = but->block; | ||||
| uiBut *bt; | |||||
| if (but->type == UI_BTYPE_GRIP) { | if (but->type == UI_BTYPE_GRIP) { | ||||
| WM_cursor_modal_restore(win); | WM_cursor_modal_restore(win); | ||||
| } | } | ||||
| /* ensure we are in the exit state */ | /* ensure we are in the exit state */ | ||||
| if (data->state != BUTTON_STATE_EXIT) { | if (data->state != BUTTON_STATE_EXIT) { | ||||
| button_activate_state(C, but, BUTTON_STATE_EXIT); | button_activate_state(C, but, BUTTON_STATE_EXIT); | ||||
| } | } | ||||
| /* apply the button action or value */ | /* apply the button action or value */ | ||||
| if (!onfree) { | if (!onfree) { | ||||
| ui_apply_but(C, block, but, data, false); | ui_apply_but(C, block, but, data, false); | ||||
| } | } | ||||
| #ifdef USE_DRAG_MULTINUM | #ifdef USE_DRAG_MULTINUM | ||||
| if (data->multi_data.has_mbuts) { | if (data->multi_data.has_mbuts) { | ||||
| for (bt = block->buttons.first; bt; bt = bt->next) { | LISTBASE_FOREACH (uiBut *, bt, &block->buttons) { | ||||
| if (bt->flag & UI_BUT_DRAG_MULTI) { | if (bt->flag & UI_BUT_DRAG_MULTI) { | ||||
| bt->flag &= ~UI_BUT_DRAG_MULTI; | bt->flag &= ~UI_BUT_DRAG_MULTI; | ||||
| if (!data->cancel) { | if (!data->cancel) { | ||||
| ui_apply_but_autokey(C, bt); | ui_apply_but_autokey(C, bt); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Show All 39 Lines | #endif | ||||
| } | } | ||||
| if (U.runtime.is_dirty == false) { | if (U.runtime.is_dirty == false) { | ||||
| ui_but_update_preferences_dirty(but); | ui_but_update_preferences_dirty(but); | ||||
| } | } | ||||
| } | } | ||||
| /* disable tooltips until mousemove + last active flag */ | /* disable tooltips until mousemove + last active flag */ | ||||
| for (block = data->region->uiblocks.first; block; block = block->next) { | LISTBASE_FOREACH (uiBlock *, block_iter, &data->region->uiblocks) { | ||||
| for (bt = block->buttons.first; bt; bt = bt->next) { | LISTBASE_FOREACH (uiBut *, bt, &block_iter->buttons) { | ||||
| bt->flag &= ~UI_BUT_LAST_ACTIVE; | bt->flag &= ~UI_BUT_LAST_ACTIVE; | ||||
| } | } | ||||
| block->tooltipdisabled = 1; | block_iter->tooltipdisabled = 1; | ||||
| } | } | ||||
| ui_blocks_set_tooltips(data->region, false); | ui_blocks_set_tooltips(data->region, false); | ||||
| /* clean up */ | /* clean up */ | ||||
| if (data->str) { | if (data->str) { | ||||
| MEM_freeN(data->str); | MEM_freeN(data->str); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /* returns the active button with an optional checking function */ | /* returns the active button with an optional checking function */ | ||||
| static uiBut *ui_context_button_active(ARegion *region, bool (*but_check_cb)(uiBut *)) | static uiBut *ui_context_button_active(ARegion *region, bool (*but_check_cb)(uiBut *)) | ||||
| { | { | ||||
| uiBut *but_found = NULL; | uiBut *but_found = NULL; | ||||
| while (region) { | while (region) { | ||||
| uiBlock *block; | uiBut *activebut = NULL; | ||||
| uiBut *but, *activebut = NULL; | |||||
| /* find active button */ | /* find active button */ | ||||
| for (block = region->uiblocks.first; block; block = block->next) { | LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { | ||||
| for (but = block->buttons.first; but; but = but->next) { | LISTBASE_FOREACH (uiBut *, but, &block->buttons) { | ||||
| if (but->active) { | if (but->active) { | ||||
| activebut = but; | activebut = but; | ||||
| } | } | ||||
| else if (!activebut && (but->flag & UI_BUT_LAST_ACTIVE)) { | else if (!activebut && (but->flag & UI_BUT_LAST_ACTIVE)) { | ||||
| activebut = but; | activebut = but; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | |||||
| void UI_context_active_but_clear(bContext *C, wmWindow *win, ARegion *region) | void UI_context_active_but_clear(bContext *C, wmWindow *win, ARegion *region) | ||||
| { | { | ||||
| wm_event_handler_ui_cancel_ex(C, win, region, false); | wm_event_handler_ui_cancel_ex(C, win, region, false); | ||||
| } | } | ||||
| wmOperator *UI_context_active_operator_get(const struct bContext *C) | wmOperator *UI_context_active_operator_get(const struct bContext *C) | ||||
| { | { | ||||
| ARegion *region_ctx = CTX_wm_region(C); | ARegion *region_ctx = CTX_wm_region(C); | ||||
| uiBlock *block; | |||||
| /* background mode */ | /* background mode */ | ||||
| if (region_ctx == NULL) { | if (region_ctx == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* scan active regions ui */ | /* scan active regions ui */ | ||||
| for (block = region_ctx->uiblocks.first; block; block = block->next) { | LISTBASE_FOREACH (uiBlock *, block, ®ion_ctx->uiblocks) { | ||||
| if (block->ui_operator) { | if (block->ui_operator) { | ||||
| return block->ui_operator; | return block->ui_operator; | ||||
| } | } | ||||
| } | } | ||||
| /* scan popups */ | /* scan popups */ | ||||
| { | { | ||||
| bScreen *screen = CTX_wm_screen(C); | bScreen *screen = CTX_wm_screen(C); | ||||
| ARegion *region; | |||||
| for (region = screen->regionbase.first; region; region = region->next) { | LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) { | ||||
| if (region == region_ctx) { | if (region == region_ctx) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| for (block = region->uiblocks.first; block; block = block->next) { | LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { | ||||
| if (block->ui_operator) { | if (block->ui_operator) { | ||||
| return block->ui_operator; | return block->ui_operator; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* helper function for insert keyframe, reset to default, etc operators */ | /* helper function for insert keyframe, reset to default, etc operators */ | ||||
| void UI_context_update_anim_flag(const bContext *C) | void UI_context_update_anim_flag(const bContext *C) | ||||
| { | { | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| ARegion *region = CTX_wm_region(C); | ARegion *region = CTX_wm_region(C); | ||||
| struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); | struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); | ||||
| const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( | const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( | ||||
| depsgraph, (scene) ? scene->r.cfra : 0.0f); | depsgraph, (scene) ? scene->r.cfra : 0.0f); | ||||
| uiBlock *block; | uiBut *activebut; | ||||
| uiBut *but, *activebut; | |||||
| while (region) { | while (region) { | ||||
| /* find active button */ | /* find active button */ | ||||
| activebut = NULL; | activebut = NULL; | ||||
| for (block = region->uiblocks.first; block; block = block->next) { | LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { | ||||
| for (but = block->buttons.first; but; but = but->next) { | LISTBASE_FOREACH (uiBut *, but, &block->buttons) { | ||||
| ui_but_anim_flag(but, &anim_eval_context); | ui_but_anim_flag(but, &anim_eval_context); | ||||
| ui_but_override_flag(CTX_data_main(C), but); | ui_but_override_flag(CTX_data_main(C), but); | ||||
| if (UI_but_is_decorator(but)) { | if (UI_but_is_decorator(but)) { | ||||
| ui_but_anim_decorate_update_from_flag((uiButDecorator *)but); | ui_but_anim_decorate_update_from_flag((uiButDecorator *)but); | ||||
| } | } | ||||
| ED_region_tag_redraw(region); | ED_region_tag_redraw(region); | ||||
| Show All 26 Lines | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Button Activation Handling | /** \name Button Activation Handling | ||||
| * \{ */ | * \{ */ | ||||
| static uiBut *ui_but_find_open_event(ARegion *region, const wmEvent *event) | static uiBut *ui_but_find_open_event(ARegion *region, const wmEvent *event) | ||||
| { | { | ||||
| uiBlock *block; | LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { | ||||
| uiBut *but; | LISTBASE_FOREACH (uiBut *, but, &block->buttons) { | ||||
| for (block = region->uiblocks.first; block; block = block->next) { | |||||
| for (but = block->buttons.first; but; but = but->next) { | |||||
| if (but == event->customdata) { | if (but == event->customdata) { | ||||
| return but; | return but; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,739 Lines • ▼ Show 20 Lines | else { | ||||
| ED_region_tag_redraw(menu->region); | ED_region_tag_redraw(menu->region); | ||||
| } | } | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| static uiBut *ui_block_pie_dir_activate(uiBlock *block, const wmEvent *event, RadialDirection dir) | static uiBut *ui_block_pie_dir_activate(uiBlock *block, const wmEvent *event, RadialDirection dir) | ||||
| { | { | ||||
| uiBut *but; | |||||
| if ((block->flag & UI_BLOCK_NUMSELECT) && event->val == KM_PRESS) { | if ((block->flag & UI_BLOCK_NUMSELECT) && event->val == KM_PRESS) { | ||||
| for (but = block->buttons.first; but; but = but->next) { | LISTBASE_FOREACH (uiBut *, but, &block->buttons) { | ||||
| if (but->pie_dir == dir && !ELEM(but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) { | if (but->pie_dir == dir && !ELEM(but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) { | ||||
| return but; | return but; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| Show All 15 Lines | static int ui_but_pie_button_activate(bContext *C, uiBut *but, uiPopupBlockHandle *menu) | ||||
| button_activate_init(C, menu->region, but, BUTTON_ACTIVATE_OVER); | button_activate_init(C, menu->region, but, BUTTON_ACTIVATE_OVER); | ||||
| return ui_but_pie_menu_apply(C, menu, but, false); | return ui_but_pie_menu_apply(C, menu, but, false); | ||||
| } | } | ||||
| static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu) | static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu) | ||||
| { | { | ||||
| ARegion *region; | ARegion *region; | ||||
| uiBlock *block; | uiBlock *block; | ||||
| uiBut *but; | |||||
| float event_xy[2]; | float event_xy[2]; | ||||
| double duration; | double duration; | ||||
| bool is_click_style; | bool is_click_style; | ||||
| float dist; | float dist; | ||||
| /* we block all events, this is modal interaction, | /* we block all events, this is modal interaction, | ||||
| * except for drop events which is described below */ | * except for drop events which is described below */ | ||||
| int retval = WM_UI_HANDLER_BREAK; | int retval = WM_UI_HANDLER_BREAK; | ||||
| if (event->type == EVT_DROP) { | if (event->type == EVT_DROP) { | ||||
| /* may want to leave this here for later if we support pie ovens */ | /* may want to leave this here for later if we support pie ovens */ | ||||
| retval = WM_UI_HANDLER_CONTINUE; | retval = WM_UI_HANDLER_CONTINUE; | ||||
| } | } | ||||
| region = menu->region; | region = menu->region; | ||||
| block = region->uiblocks.first; | block = region->uiblocks.first; | ||||
| is_click_style = (block->pie_data.flags & UI_PIE_CLICK_STYLE); | is_click_style = (block->pie_data.flags & UI_PIE_CLICK_STYLE); | ||||
| /* if there's an active modal button, don't check events or outside, except for search menu */ | /* if there's an active modal button, don't check events or outside, except for search menu */ | ||||
| but = ui_region_find_active_but(region); | uiBut *but_active = ui_region_find_active_but(region); | ||||
| if (menu->scrolltimer == NULL) { | if (menu->scrolltimer == NULL) { | ||||
| menu->scrolltimer = WM_event_add_timer( | menu->scrolltimer = WM_event_add_timer( | ||||
| CTX_wm_manager(C), CTX_wm_window(C), TIMER, PIE_MENU_INTERVAL); | CTX_wm_manager(C), CTX_wm_window(C), TIMER, PIE_MENU_INTERVAL); | ||||
| menu->scrolltimer->duration = 0.0; | menu->scrolltimer->duration = 0.0; | ||||
| } | } | ||||
| duration = menu->scrolltimer->duration; | duration = menu->scrolltimer->duration; | ||||
| event_xy[0] = event->x; | event_xy[0] = event->x; | ||||
| event_xy[1] = event->y; | event_xy[1] = event->y; | ||||
| ui_window_to_block_fl(region, block, &event_xy[0], &event_xy[1]); | ui_window_to_block_fl(region, block, &event_xy[0], &event_xy[1]); | ||||
| /* Distance from initial point. */ | /* Distance from initial point. */ | ||||
| dist = ui_block_calc_pie_segment(block, event_xy); | dist = ui_block_calc_pie_segment(block, event_xy); | ||||
| if (but && button_modal_state(but->active->state)) { | if (but_active && button_modal_state(but_active->active->state)) { | ||||
| retval = ui_handle_menu_button(C, event, menu); | retval = ui_handle_menu_button(C, event, menu); | ||||
| } | } | ||||
| else { | else { | ||||
| if (event->type == TIMER) { | if (event->type == TIMER) { | ||||
| if (event->customdata == menu->scrolltimer) { | if (event->customdata == menu->scrolltimer) { | ||||
| /* deactivate initial direction after a while */ | /* deactivate initial direction after a while */ | ||||
| if (duration > 0.01 * U.pie_initial_timeout) { | if (duration > 0.01 * U.pie_initial_timeout) { | ||||
| block->pie_data.flags &= ~UI_PIE_INITIAL_DIRECTION; | block->pie_data.flags &= ~UI_PIE_INITIAL_DIRECTION; | ||||
| } | } | ||||
| /* handle animation */ | /* handle animation */ | ||||
| if (!(block->pie_data.flags & UI_PIE_ANIMATION_FINISHED)) { | if (!(block->pie_data.flags & UI_PIE_ANIMATION_FINISHED)) { | ||||
| double final_time = 0.01 * U.pie_animation_timeout; | double final_time = 0.01 * U.pie_animation_timeout; | ||||
| float fac = duration / final_time; | float fac = duration / final_time; | ||||
| float pie_radius = U.pie_menu_radius * UI_DPI_FAC; | float pie_radius = U.pie_menu_radius * UI_DPI_FAC; | ||||
| if (fac > 1.0f) { | if (fac > 1.0f) { | ||||
| fac = 1.0f; | fac = 1.0f; | ||||
| block->pie_data.flags |= UI_PIE_ANIMATION_FINISHED; | block->pie_data.flags |= UI_PIE_ANIMATION_FINISHED; | ||||
| } | } | ||||
| for (but = block->buttons.first; but; but = but->next) { | LISTBASE_FOREACH (uiBut *, but, &block->buttons) { | ||||
| if (but->pie_dir != UI_RADIAL_NONE) { | if (but->pie_dir != UI_RADIAL_NONE) { | ||||
| float vec[2]; | float vec[2]; | ||||
| float center[2]; | float center[2]; | ||||
| ui_but_pie_dir(but->pie_dir, vec); | ui_but_pie_dir(but->pie_dir, vec); | ||||
| center[0] = (vec[0] > 0.01f) ? 0.5f : ((vec[0] < -0.01f) ? -0.5f : 0.0f); | center[0] = (vec[0] > 0.01f) ? 0.5f : ((vec[0] < -0.01f) ? -0.5f : 0.0f); | ||||
| center[1] = (vec[1] > 0.99f) ? 0.5f : ((vec[1] < -0.99f) ? -0.5f : 0.0f); | center[1] = (vec[1] > 0.99f) ? 0.5f : ((vec[1] < -0.99f) ? -0.5f : 0.0f); | ||||
| Show All 22 Lines | if (event->type == TIMER) { | ||||
| /* use a time threshold to ensure we leave time to the mouse to move */ | /* use a time threshold to ensure we leave time to the mouse to move */ | ||||
| if (duration - block->pie_data.duration_gesture > 0.02) { | if (duration - block->pie_data.duration_gesture > 0.02) { | ||||
| len_sq = len_squared_v2v2(event_xy, block->pie_data.last_pos); | len_sq = len_squared_v2v2(event_xy, block->pie_data.last_pos); | ||||
| copy_v2_v2(block->pie_data.last_pos, event_xy); | copy_v2_v2(block->pie_data.last_pos, event_xy); | ||||
| block->pie_data.duration_gesture = duration; | block->pie_data.duration_gesture = duration; | ||||
| } | } | ||||
| if (len_sq < 1.0f) { | if (len_sq < 1.0f) { | ||||
| but = ui_region_find_active_but(menu->region); | uiBut *but = ui_region_find_active_but(menu->region); | ||||
| if (but) { | if (but) { | ||||
| return ui_but_pie_menu_apply(C, menu, but, true); | return ui_but_pie_menu_apply(C, menu, but, true); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Show All 9 Lines | if (event->type == block->pie_data.event && !is_click_style) { | ||||
| ED_region_tag_redraw(region); | ED_region_tag_redraw(region); | ||||
| } | } | ||||
| else { | else { | ||||
| if ((duration < 0.01 * U.pie_tap_timeout) && | if ((duration < 0.01 * U.pie_tap_timeout) && | ||||
| !(block->pie_data.flags & UI_PIE_DRAG_STYLE)) { | !(block->pie_data.flags & UI_PIE_DRAG_STYLE)) { | ||||
| block->pie_data.flags |= UI_PIE_CLICK_STYLE; | block->pie_data.flags |= UI_PIE_CLICK_STYLE; | ||||
| } | } | ||||
| else { | else { | ||||
| but = ui_region_find_active_but(menu->region); | uiBut *but = ui_region_find_active_but(menu->region); | ||||
| if (but && (U.pie_menu_confirm > 0) && | if (but && (U.pie_menu_confirm > 0) && | ||||
| (dist >= U.dpi_fac * (U.pie_menu_threshold + U.pie_menu_confirm))) { | (dist >= U.dpi_fac * (U.pie_menu_threshold + U.pie_menu_confirm))) { | ||||
| return ui_but_pie_menu_apply(C, menu, but, true); | return ui_but_pie_menu_apply(C, menu, but, true); | ||||
| } | } | ||||
| retval = ui_but_pie_menu_apply(C, menu, but, true); | retval = ui_but_pie_menu_apply(C, menu, but, true); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | else { | ||||
| case EVT_UKEY: | case EVT_UKEY: | ||||
| case EVT_VKEY: | case EVT_VKEY: | ||||
| case EVT_WKEY: | case EVT_WKEY: | ||||
| case EVT_XKEY: | case EVT_XKEY: | ||||
| case EVT_YKEY: | case EVT_YKEY: | ||||
| case EVT_ZKEY: { | case EVT_ZKEY: { | ||||
| if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) && | if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) && | ||||
| !IS_EVENT_MOD(event, shift, ctrl, oskey)) { | !IS_EVENT_MOD(event, shift, ctrl, oskey)) { | ||||
| for (but = block->buttons.first; but; but = but->next) { | LISTBASE_FOREACH (uiBut *, but, &block->buttons) { | ||||
| if (but->menu_key == event->type) { | if (but->menu_key == event->type) { | ||||
| ui_but_pie_button_activate(C, but, menu); | ui_but_pie_button_activate(C, but, menu); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| Show All 16 Lines | (void)0 | ||||
| CASE_NUM_TO_DIR(6, UI_RADIAL_E); | CASE_NUM_TO_DIR(6, UI_RADIAL_E); | ||||
| ATTR_FALLTHROUGH; | ATTR_FALLTHROUGH; | ||||
| CASE_NUM_TO_DIR(7, UI_RADIAL_NW); | CASE_NUM_TO_DIR(7, UI_RADIAL_NW); | ||||
| ATTR_FALLTHROUGH; | ATTR_FALLTHROUGH; | ||||
| CASE_NUM_TO_DIR(8, UI_RADIAL_N); | CASE_NUM_TO_DIR(8, UI_RADIAL_N); | ||||
| ATTR_FALLTHROUGH; | ATTR_FALLTHROUGH; | ||||
| CASE_NUM_TO_DIR(9, UI_RADIAL_NE); | CASE_NUM_TO_DIR(9, UI_RADIAL_NE); | ||||
| { | { | ||||
| but = ui_block_pie_dir_activate(block, event, num_dir); | uiBut *but = ui_block_pie_dir_activate(block, event, num_dir); | ||||
| retval = ui_but_pie_button_activate(C, but, menu); | retval = ui_but_pie_button_activate(C, but, menu); | ||||
| break; | break; | ||||
| } | } | ||||
| #undef CASE_NUM_TO_DIR | #undef CASE_NUM_TO_DIR | ||||
| default: | default: | ||||
| retval = ui_handle_menu_button(C, event, menu); | retval = ui_handle_menu_button(C, event, menu); | ||||
| break; | break; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 447 Lines • ▼ Show 20 Lines | void UI_popup_handlers_remove_all(bContext *C, ListBase *handlers) | ||||
| WM_event_free_ui_handler_all(C, handlers, ui_popup_handler, ui_popup_handler_remove); | WM_event_free_ui_handler_all(C, handlers, ui_popup_handler, ui_popup_handler_remove); | ||||
| } | } | ||||
| bool UI_textbutton_activate_rna(const bContext *C, | bool UI_textbutton_activate_rna(const bContext *C, | ||||
| ARegion *region, | ARegion *region, | ||||
| const void *rna_poin_data, | const void *rna_poin_data, | ||||
| const char *rna_prop_id) | const char *rna_prop_id) | ||||
| { | { | ||||
| uiBlock *block; | uiBlock *block_text = NULL; | ||||
| uiBut *but = NULL; | uiBut *but_text = NULL; | ||||
| for (block = region->uiblocks.first; block; block = block->next) { | LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { | ||||
| for (but = block->buttons.first; but; but = but->next) { | LISTBASE_FOREACH (uiBut *, but, &block->buttons) { | ||||
| if (but->type == UI_BTYPE_TEXT) { | if (but->type == UI_BTYPE_TEXT) { | ||||
| if (but->rnaprop && but->rnapoin.data == rna_poin_data) { | if (but->rnaprop && but->rnapoin.data == rna_poin_data) { | ||||
| if (STREQ(RNA_property_identifier(but->rnaprop), rna_prop_id)) { | if (STREQ(RNA_property_identifier(but->rnaprop), rna_prop_id)) { | ||||
| block_text = block; | |||||
| but_text = but; | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (but) { | if (but_text) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (but) { | if (but_text) { | ||||
| UI_but_active_only(C, region, block, but); | UI_but_active_only(C, region, block_text, but_text); | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| bool UI_textbutton_activate_but(const bContext *C, uiBut *actbut) | bool UI_textbutton_activate_but(const bContext *C, uiBut *actbut) | ||||
| { | { | ||||
| ARegion *region = CTX_wm_region(C); | ARegion *region = CTX_wm_region(C); | ||||
| uiBlock *block; | uiBlock *block_text = NULL; | ||||
| uiBut *but = NULL; | uiBut *but_text = NULL; | ||||
| for (block = region->uiblocks.first; block; block = block->next) { | LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { | ||||
| for (but = block->buttons.first; but; but = but->next) { | LISTBASE_FOREACH (uiBut *, but, &block->buttons) { | ||||
| if (but == actbut && but->type == UI_BTYPE_TEXT) { | if (but == actbut && but->type == UI_BTYPE_TEXT) { | ||||
| block_text = block; | |||||
| but_text = but; | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (but) { | if (but_text) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (but) { | if (but_text) { | ||||
| UI_but_active_only(C, region, block, but); | UI_but_active_only(C, region, block_text, but_text); | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| ▲ Show 20 Lines • Show All 56 Lines • Show Last 20 Lines | |||||