Changeset View
Changeset View
Standalone View
Standalone View
source/blender/windowmanager/intern/wm_event_system.c
| Show First 20 Lines • Show All 947 Lines • ▼ Show 20 Lines | |||||
| */ | */ | ||||
| static bool wm_operator_register_check(wmWindowManager *wm, wmOperatorType *ot) | static bool wm_operator_register_check(wmWindowManager *wm, wmOperatorType *ot) | ||||
| { | { | ||||
| /* Check undo flag here since undo operators are also added to the list, | /* Check undo flag here since undo operators are also added to the list, | ||||
| * to support checking if the same operator is run twice. */ | * to support checking if the same operator is run twice. */ | ||||
| return wm && (wm->op_undo_depth == 0) && (ot->flag & (OPTYPE_REGISTER | OPTYPE_UNDO)); | return wm && (wm->op_undo_depth == 0) && (ot->flag & (OPTYPE_REGISTER | OPTYPE_UNDO)); | ||||
| } | } | ||||
| static void wm_operator_finished(bContext *C, wmOperator *op, const bool repeat, const bool store) | struct wmOperatorFinishedData { | ||||
| /** To detect when the scene changes. */ | |||||
| Scene *scene; | |||||
| /** To detect when the frame changes. */ | |||||
| int scene_frame; | |||||
| }; | |||||
| static void wm_operator_finished_pre_setup(bContext *C, | |||||
| struct wmOperatorFinishedData *op_finished_data) | |||||
| { | |||||
| op_finished_data->scene = CTX_data_scene(C); | |||||
| op_finished_data->scene_frame = op_finished_data->scene->r.cfra; | |||||
| } | |||||
| static void wm_operator_finished(bContext *C, | |||||
| wmOperator *op, | |||||
| const bool repeat, | |||||
| const bool store, | |||||
| struct wmOperatorFinishedData *op_finished_data) | |||||
| { | { | ||||
| wmWindowManager *wm = CTX_wm_manager(C); | wmWindowManager *wm = CTX_wm_manager(C); | ||||
| enum { | enum { | ||||
| NOP, | NOP, | ||||
| SET, | SET, | ||||
| CLEAR, | CLEAR, | ||||
| } hud_status = NOP; | } hud_status = NOP; | ||||
| op->customdata = NULL; | op->customdata = NULL; | ||||
| if (store) { | if (store) { | ||||
| WM_operator_last_properties_store(op); | WM_operator_last_properties_store(op); | ||||
| } | } | ||||
| /* We don't want to do undo pushes for operators that are being | /* We don't want to do undo pushes for operators that are being | ||||
| * called from operators that already do an undo push. Usually | * called from operators that already do an undo push. Usually | ||||
| * this will happen for python operators that call C operators. */ | * this will happen for python operators that call C operators. */ | ||||
| if (wm->op_undo_depth == 0) { | if ((wm->op_undo_depth == 0) && (op->type->flag & (OPTYPE_UNDO | OPTYPE_UNDO_GROUPED))) { | ||||
| if (G.is_rendering == false) { | |||||
| const bool is_anim = (op_finished_data->scene == CTX_data_scene(C)) && | |||||
| (op_finished_data->scene_frame != op_finished_data->scene->r.cfra); | |||||
| if (is_anim) { | |||||
| Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); | |||||
| ED_update_for_newframe(CTX_data_main(C), depsgraph); | |||||
| } | |||||
| } | |||||
| if (op->type->flag & OPTYPE_UNDO) { | if (op->type->flag & OPTYPE_UNDO) { | ||||
| ED_undo_push_op(C, op); | ED_undo_push_op(C, op); | ||||
| if (repeat == 0) { | if (repeat == 0) { | ||||
| hud_status = CLEAR; | hud_status = CLEAR; | ||||
| } | } | ||||
| } | } | ||||
| else if (op->type->flag & OPTYPE_UNDO_GROUPED) { | else if (op->type->flag & OPTYPE_UNDO_GROUPED) { | ||||
| ED_undo_grouped_push_op(C, op); | ED_undo_grouped_push_op(C, op); | ||||
| ▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | static int wm_operator_exec(bContext *C, wmOperator *op, const bool repeat, const bool store) | ||||
| if (op == NULL || op->type == NULL) { | if (op == NULL || op->type == NULL) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| if (0 == WM_operator_poll(C, op->type)) { | if (0 == WM_operator_poll(C, op->type)) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| struct wmOperatorFinishedData op_finished_data = {NULL}; | |||||
| wm_operator_finished_pre_setup(C, &op_finished_data); | |||||
| if (op->type->exec) { | if (op->type->exec) { | ||||
| if (op->type->flag & OPTYPE_UNDO) { | if (op->type->flag & OPTYPE_UNDO) { | ||||
| wm->op_undo_depth++; | wm->op_undo_depth++; | ||||
| } | } | ||||
| retval = op->type->exec(C, op); | retval = op->type->exec(C, op); | ||||
| OPERATOR_RETVAL_CHECK(retval); | OPERATOR_RETVAL_CHECK(retval); | ||||
| if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) { | if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) { | ||||
| wm->op_undo_depth--; | wm->op_undo_depth--; | ||||
| } | } | ||||
| } | } | ||||
| /* XXX(mont29) Disabled the repeat check to address part 2 of T31840. | /* XXX(mont29) Disabled the repeat check to address part 2 of T31840. | ||||
| * Carefully checked all calls to wm_operator_exec and WM_operator_repeat, don't see any reason | * Carefully checked all calls to wm_operator_exec and WM_operator_repeat, don't see any reason | ||||
| * why this was needed, but worth to note it in case something turns bad. */ | * why this was needed, but worth to note it in case something turns bad. */ | ||||
| if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED) /* && repeat == 0 */) { | if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED) /* && repeat == 0 */) { | ||||
| wm_operator_reports(C, op, retval, false); | wm_operator_reports(C, op, retval, false); | ||||
| } | } | ||||
| if (retval & OPERATOR_FINISHED) { | if (retval & OPERATOR_FINISHED) { | ||||
| wm_operator_finished(C, op, repeat, store && wm->op_undo_depth == 0); | wm_operator_finished(C, op, repeat, store && wm->op_undo_depth == 0, &op_finished_data); | ||||
| } | } | ||||
| else if (repeat == 0) { | else if (repeat == 0) { | ||||
| /* warning: modal from exec is bad practice, but avoid crashing. */ | /* warning: modal from exec is bad practice, but avoid crashing. */ | ||||
| if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) { | if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) { | ||||
| WM_operator_free(op); | WM_operator_free(op); | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 223 Lines • ▼ Show 20 Lines | if ((event == NULL) || (event->type != MOUSEMOVE)) { | ||||
| CLOG_INFO(WM_LOG_HANDLERS, | CLOG_INFO(WM_LOG_HANDLERS, | ||||
| 2, | 2, | ||||
| "handle evt %d win %p op %s", | "handle evt %d win %p op %s", | ||||
| event ? event->type : 0, | event ? event->type : 0, | ||||
| CTX_wm_screen(C)->active_region, | CTX_wm_screen(C)->active_region, | ||||
| ot->idname); | ot->idname); | ||||
| } | } | ||||
| struct wmOperatorFinishedData op_finished_data = {NULL}; | |||||
| wm_operator_finished_pre_setup(C, &op_finished_data); | |||||
| if (op->type->invoke && event) { | if (op->type->invoke && event) { | ||||
| wm_region_mouse_co(C, event); | wm_region_mouse_co(C, event); | ||||
| if (op->type->flag & OPTYPE_UNDO) { | if (op->type->flag & OPTYPE_UNDO) { | ||||
| wm->op_undo_depth++; | wm->op_undo_depth++; | ||||
| } | } | ||||
| retval = op->type->invoke(C, op, event); | retval = op->type->invoke(C, op, event); | ||||
| Show All 27 Lines | if (!(retval & OPERATOR_HANDLED) && (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED))) { | ||||
| wm_operator_reports(C, op, retval, (reports != NULL)); | wm_operator_reports(C, op, retval, (reports != NULL)); | ||||
| } | } | ||||
| if (retval & OPERATOR_HANDLED) { | if (retval & OPERATOR_HANDLED) { | ||||
| /* Do nothing, wm_operator_exec() has been called somewhere. */ | /* Do nothing, wm_operator_exec() has been called somewhere. */ | ||||
| } | } | ||||
| else if (retval & OPERATOR_FINISHED) { | else if (retval & OPERATOR_FINISHED) { | ||||
| const bool store = !is_nested_call && use_last_properties; | const bool store = !is_nested_call && use_last_properties; | ||||
| wm_operator_finished(C, op, false, store); | wm_operator_finished(C, op, false, store, &op_finished_data); | ||||
| } | } | ||||
| else if (retval & OPERATOR_RUNNING_MODAL) { | else if (retval & OPERATOR_RUNNING_MODAL) { | ||||
| /* Take ownership of reports (in case python provided own). */ | /* Take ownership of reports (in case python provided own). */ | ||||
| op->reports->flag |= RPT_FREE; | op->reports->flag |= RPT_FREE; | ||||
| /* Grab cursor during blocking modal ops (X11) | /* Grab cursor during blocking modal ops (X11) | ||||
| * Also check for macro. | * Also check for macro. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 847 Lines • ▼ Show 20 Lines | else if (ot->modal) { | ||||
| ARegion *region = CTX_wm_region(C); | ARegion *region = CTX_wm_region(C); | ||||
| wm_handler_op_context(C, handler, event); | wm_handler_op_context(C, handler, event); | ||||
| wm_region_mouse_co(C, event); | wm_region_mouse_co(C, event); | ||||
| struct wmEvent_ModalMapStore event_backup; | struct wmEvent_ModalMapStore event_backup; | ||||
| wm_event_modalkeymap_begin(C, op, event, &event_backup); | wm_event_modalkeymap_begin(C, op, event, &event_backup); | ||||
| struct wmOperatorFinishedData op_finished_data = {NULL}; | |||||
| wm_operator_finished_pre_setup(C, &op_finished_data); | |||||
| if (ot->flag & OPTYPE_UNDO) { | if (ot->flag & OPTYPE_UNDO) { | ||||
| wm->op_undo_depth++; | wm->op_undo_depth++; | ||||
| } | } | ||||
| /* Warning, after this call all context data and 'event' may be freed. see check below. */ | /* Warning, after this call all context data and 'event' may be freed. see check below. */ | ||||
| retval = ot->modal(C, op, event); | retval = ot->modal(C, op, event); | ||||
| OPERATOR_RETVAL_CHECK(retval); | OPERATOR_RETVAL_CHECK(retval); | ||||
| Show All 19 Lines | else if (ot->modal) { | ||||
| /* Not very common, but modal operators may report before finishing. */ | /* Not very common, but modal operators may report before finishing. */ | ||||
| if (!BLI_listbase_is_empty(&op->reports->list)) { | if (!BLI_listbase_is_empty(&op->reports->list)) { | ||||
| wm_add_reports(op->reports); | wm_add_reports(op->reports); | ||||
| } | } | ||||
| } | } | ||||
| /* Important to run 'wm_operator_finished' before NULLing the context members. */ | /* Important to run 'wm_operator_finished' before NULLing the context members. */ | ||||
| if (retval & OPERATOR_FINISHED) { | if (retval & OPERATOR_FINISHED) { | ||||
| wm_operator_finished(C, op, false, true); | wm_operator_finished(C, op, false, true, &op_finished_data); | ||||
| handler->op = NULL; | handler->op = NULL; | ||||
| } | } | ||||
| else if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { | else if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { | ||||
| WM_operator_free(op); | WM_operator_free(op); | ||||
| handler->op = NULL; | handler->op = NULL; | ||||
| } | } | ||||
| /* Putting back screen context, reval can pass through after modal failures! */ | /* Putting back screen context, reval can pass through after modal failures! */ | ||||
| ▲ Show 20 Lines • Show All 3,309 Lines • Show Last 20 Lines | |||||