Fix #113309: Broken key-map after "Reload Scripts"
Regression caused by [0]. Resolve by adding a 'keep_properties' argument
to KeyConfig.update so the key-map items can be restored after the
operators have been reloaded.
[0]: 88a875ec3a
This commit is contained in:
@@ -292,7 +292,7 @@ def load_scripts(*, reload_scripts=False, refresh_scripts=False, extensions=True
|
||||
# however reloading scripts re-enable all add-ons immediately (which may inspect key-maps).
|
||||
# For this reason it's important to update key-maps which will have been tagged to update.
|
||||
# Without this, add-on register functions accessing key-map properties can crash, see: #111702.
|
||||
_bpy.context.window_manager.keyconfigs.update()
|
||||
_bpy.context.window_manager.keyconfigs.update(keep_properties=True)
|
||||
|
||||
from bpy_restrict_state import RestrictBlend
|
||||
|
||||
@@ -308,6 +308,11 @@ def load_scripts(*, reload_scripts=False, refresh_scripts=False, extensions=True
|
||||
for mod in modules_from_path(path, loaded_modules):
|
||||
test_register(mod)
|
||||
|
||||
if reload_scripts:
|
||||
# Update key-maps for key-map items referencing operators defined in "startup".
|
||||
# Without this, key-map items wont be set properly, see: #113309.
|
||||
_bpy.context.window_manager.keyconfigs.update()
|
||||
|
||||
if extensions:
|
||||
load_scripts_extensions(reload_scripts=reload_scripts)
|
||||
|
||||
|
||||
@@ -539,9 +539,9 @@ static PointerRNA rna_KeyConfig_find_item_from_operator(wmWindowManager *wm,
|
||||
return kmi_ptr;
|
||||
}
|
||||
|
||||
static void rna_KeyConfig_update(wmWindowManager *wm)
|
||||
static void rna_KeyConfig_update(wmWindowManager *wm, bool keep_properties)
|
||||
{
|
||||
WM_keyconfig_update(wm);
|
||||
WM_keyconfig_update_ex(wm, keep_properties);
|
||||
}
|
||||
|
||||
/* popup menu wrapper */
|
||||
@@ -1335,7 +1335,13 @@ void RNA_api_keyconfigs(StructRNA *srna)
|
||||
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_RNAPTR);
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
RNA_def_function(srna, "update", "rna_KeyConfig_update"); /* WM_keyconfig_update */
|
||||
func = RNA_def_function(srna, "update", "rna_KeyConfig_update"); /* WM_keyconfig_update */
|
||||
RNA_def_boolean(
|
||||
func,
|
||||
"keep_properties",
|
||||
false,
|
||||
"Keep Properties",
|
||||
"Operator properties are kept to allow the operators to be registered again in the future");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,12 @@ void WM_keyconfig_free(wmKeyConfig *keyconf);
|
||||
|
||||
void WM_keyconfig_set_active(wmWindowManager *wm, const char *idname);
|
||||
|
||||
/**
|
||||
* \param keep_properties: When true, the properties for operators which cannot be found are kept.
|
||||
* This is needed for operator reloading that validates key-map items for operators that may have
|
||||
* their operators loaded back in the future, see: #113309.
|
||||
*/
|
||||
void WM_keyconfig_update_ex(wmWindowManager *wm, bool keep_properties);
|
||||
void WM_keyconfig_update(wmWindowManager *wm);
|
||||
void WM_keyconfig_update_tag(wmKeyMap *keymap, wmKeyMapItem *kmi);
|
||||
void WM_keyconfig_update_operatortype();
|
||||
|
||||
@@ -94,6 +94,17 @@ static void wm_keymap_item_free_data(wmKeyMapItem *kmi)
|
||||
}
|
||||
}
|
||||
|
||||
static void wm_keymap_item_clear_runtime(wmKeyMapItem *kmi)
|
||||
{
|
||||
IDProperty *properties = kmi->properties;
|
||||
kmi->properties = nullptr;
|
||||
if (kmi->ptr) {
|
||||
kmi->ptr->data = nullptr;
|
||||
}
|
||||
wm_keymap_item_free_data(kmi);
|
||||
kmi->properties = properties;
|
||||
}
|
||||
|
||||
static void wm_keymap_item_properties_set(wmKeyMapItem *kmi)
|
||||
{
|
||||
WM_operator_properties_alloc(&(kmi->ptr), &(kmi->properties), kmi->idname);
|
||||
@@ -107,7 +118,7 @@ static void wm_keymap_item_properties_set(wmKeyMapItem *kmi)
|
||||
* Similar to #wm_keymap_item_properties_set
|
||||
* but checks for the #wmOperatorType having changed, see #38042.
|
||||
*/
|
||||
static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi)
|
||||
static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi, const bool keep_properties)
|
||||
{
|
||||
if (kmi->idname[0] == 0) {
|
||||
BLI_assert(kmi->ptr == nullptr);
|
||||
@@ -137,25 +148,31 @@ static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi)
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* zombie keymap item */
|
||||
wm_keymap_item_free_data(kmi);
|
||||
/* Zombie key-map item. */
|
||||
if (keep_properties) {
|
||||
wm_keymap_item_clear_runtime(kmi);
|
||||
}
|
||||
else {
|
||||
wm_keymap_item_free_data(kmi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void wm_keymap_item_properties_update_ot_from_list(ListBase *km_lb)
|
||||
static void wm_keymap_item_properties_update_ot_from_list(ListBase *km_lb,
|
||||
const bool keep_properties)
|
||||
{
|
||||
LISTBASE_FOREACH (wmKeyMap *, km, km_lb) {
|
||||
LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) {
|
||||
wm_keymap_item_properties_update_ot(kmi);
|
||||
wm_keymap_item_properties_update_ot(kmi, keep_properties);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &km->diff_items) {
|
||||
if (kmdi->add_item) {
|
||||
wm_keymap_item_properties_update_ot(kmdi->add_item);
|
||||
wm_keymap_item_properties_update_ot(kmdi->add_item, keep_properties);
|
||||
}
|
||||
if (kmdi->remove_item) {
|
||||
wm_keymap_item_properties_update_ot(kmdi->remove_item);
|
||||
wm_keymap_item_properties_update_ot(kmdi->remove_item, keep_properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1873,6 +1890,11 @@ static wmKeyMap *wm_keymap_preset(wmWindowManager *wm, wmKeyMap *km)
|
||||
}
|
||||
|
||||
void WM_keyconfig_update(wmWindowManager *wm)
|
||||
{
|
||||
WM_keyconfig_update_ex(wm, false);
|
||||
}
|
||||
|
||||
void WM_keyconfig_update_ex(wmWindowManager *wm, bool keep_properties)
|
||||
{
|
||||
bool compat_update = false;
|
||||
|
||||
@@ -1883,9 +1905,9 @@ void WM_keyconfig_update(wmWindowManager *wm)
|
||||
if (wm_keymap_update_flag & WM_KEYMAP_UPDATE_OPERATORTYPE) {
|
||||
/* One or more operator-types have been removed, this won't happen often
|
||||
* but when it does we have to check _every_ key-map item. */
|
||||
wm_keymap_item_properties_update_ot_from_list(&U.user_keymaps);
|
||||
wm_keymap_item_properties_update_ot_from_list(&U.user_keymaps, keep_properties);
|
||||
LISTBASE_FOREACH (wmKeyConfig *, kc, &wm->keyconfigs) {
|
||||
wm_keymap_item_properties_update_ot_from_list(&kc->keymaps);
|
||||
wm_keymap_item_properties_update_ot_from_list(&kc->keymaps, keep_properties);
|
||||
}
|
||||
wm_keymap_update_flag &= ~WM_KEYMAP_UPDATE_OPERATORTYPE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user