From 1d908bffddb4c9815a986305ad4588032b81deee Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 24 Jan 2019 12:06:47 +1100 Subject: WM: Repeat Last no longer reuses skip-save properties PROP_SKIP_SAVE is often used as a way to detect the difference between adjusting options from the redo panel and initial execution. Repeat last operator was executing with skip-save properties set, preventing operators from initializing them based on the context. Fixes 60777. --- source/blender/editors/screen/screen_ops.c | 2 +- source/blender/windowmanager/WM_api.h | 3 ++ .../blender/windowmanager/intern/wm_event_system.c | 54 ++++++++++++++++++++-- 3 files changed, 54 insertions(+), 5 deletions(-) (limited to 'source') diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 6d332f8e427..8736664d23c 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -3359,7 +3359,7 @@ static int repeat_last_exec(bContext *C, wmOperator *UNUSED(op)) if (lastop) { WM_operator_free_all_after(wm, lastop); - WM_operator_repeat(C, lastop); + WM_operator_repeat_interactive(C, lastop); } return OPERATOR_CANCELLED; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 4f73e731457..99e4950f3db 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -321,6 +321,8 @@ bool WM_operator_poll_context(struct bContext *C, struct wmOperatorType * int WM_operator_call_ex(struct bContext *C, struct wmOperator *op, const bool store); int WM_operator_call (struct bContext *C, struct wmOperator *op); int WM_operator_call_notest(struct bContext *C, struct wmOperator *op); + +int WM_operator_repeat_interactive(struct bContext *C, struct wmOperator *op); int WM_operator_repeat (struct bContext *C, struct wmOperator *op); bool WM_operator_repeat_check(const struct bContext *C, struct wmOperator *op); bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op); @@ -345,6 +347,7 @@ void WM_operator_last_properties_ensure(struct wmOperatorType *ot, struct wmOperator *WM_operator_last_redo(const struct bContext *C); ID *WM_operator_drop_load_path(struct bContext *C, struct wmOperator *op, const short idcode); +bool WM_operator_last_properties_init_ex(struct wmOperator *op, struct IDProperty *last_properties); bool WM_operator_last_properties_init(struct wmOperator *op); bool WM_operator_last_properties_store(struct wmOperator *op); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 5feacea9666..ad8c7bb60a3 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1040,6 +1040,42 @@ int WM_operator_repeat(bContext *C, wmOperator *op) { return wm_operator_exec(C, op, true, true); } +/** + * Execute this operator again interactively + * without using #PROP_SKIP_SAVE properties, see: T60777. + */ +int WM_operator_repeat_interactive(bContext *C, wmOperator *op) +{ + IDProperty *properties = op->properties ? IDP_New(IDP_GROUP, &(IDPropertyTemplate){0}, "wmOperatorProperties") : NULL; + PointerRNA *ptr = MEM_dupallocN(op->ptr); + + SWAP(IDProperty *, op->properties, properties); + SWAP(PointerRNA *, op->ptr, ptr); + if (op->ptr) { + op->ptr->data = op->properties; + } + + /* Use functionality to initialize from previous execution to avoid re-using PROP_SKIP_SAVE. */ + if (properties) { + WM_operator_last_properties_init_ex(op, properties); + } + + int retval = wm_operator_exec(C, op, true, true); + + SWAP(IDProperty *, op->properties, properties); + SWAP(PointerRNA *, op->ptr, ptr); + + if (properties) { + IDP_FreeProperty(properties); + MEM_freeN(properties); + } + if (ptr) { + MEM_freeN(ptr); + } + + return retval; +} + /** * \return true if #WM_operator_repeat can run * simple check for now but may become more involved. @@ -1226,13 +1262,13 @@ static bool operator_last_properties_init_impl(wmOperator *op, IDProperty *last_ return changed; } -bool WM_operator_last_properties_init(wmOperator *op) +bool WM_operator_last_properties_init_ex(wmOperator *op, IDProperty *last_properties) { bool changed = false; - if (op->type->last_properties) { - changed |= operator_last_properties_init_impl(op, op->type->last_properties); + if (last_properties) { + changed |= operator_last_properties_init_impl(op, last_properties); for (wmOperator *opm = op->macro.first; opm; opm = opm->next) { - IDProperty *idp_src = IDP_GetPropertyFromGroup(op->type->last_properties, opm->idname); + IDProperty *idp_src = IDP_GetPropertyFromGroup(last_properties, opm->idname); if (idp_src) { changed |= operator_last_properties_init_impl(opm, idp_src); } @@ -1241,6 +1277,11 @@ bool WM_operator_last_properties_init(wmOperator *op) return changed; } +bool WM_operator_last_properties_init(wmOperator *op) +{ + return WM_operator_last_properties_init_ex(op, op->type->last_properties); +} + bool WM_operator_last_properties_store(wmOperator *op) { if (op->type->last_properties) { @@ -1272,6 +1313,11 @@ bool WM_operator_last_properties_store(wmOperator *op) #else +bool WM_operator_last_properties_init_ex(wmOperator *UNUSED(op), IDProperty *UNUSED(last_properties)) +{ + return false; +} + bool WM_operator_last_properties_init(wmOperator *UNUSED(op)) { return false; -- cgit v1.2.3