RNA: add STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID flag

This flag is needed so PointerRNA structs that aren't
part of the current context can access enum values
without inspecting the context.

This is needed for keymap access, so the keymap UI and keymap
export doesn't depend on the current context.
This commit is contained in:
Campbell Barton 2021-04-16 15:04:37 +10:00
parent dc8a43c875
commit 43b08d0578
Notes: blender-bot 2023-02-14 09:44:56 +01:00
Referenced by issue #88251, "Operator Cheat Sheet" Crash 2.93.0
2 changed files with 56 additions and 50 deletions

View File

@ -636,6 +636,12 @@ typedef enum StructFlag {
STRUCT_PUBLIC_NAMESPACE = (1 << 9),
/** All subtypes are added too. */
STRUCT_PUBLIC_NAMESPACE_INHERIT = (1 << 10),
/**
* When the #PointerRNA.owner_id is NULL, this signifies the property should be accessed
* without any context (the key-map UI and import/export for example).
* So accessing the property should not read from the current context to derive values/limits.
*/
STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID = (1 << 11),
} StructFlag;
typedef int (*StructValidateFunc)(struct PointerRNA *ptr, void *data, int *have_function);

View File

@ -1623,35 +1623,35 @@ void RNA_property_enum_items_ex(bContext *C,
*r_free = false;
if (!use_static && eprop->item_fn && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
const EnumPropertyItem *item;
if (!use_static && (eprop->item_fn != NULL)) {
const bool no_context = (prop->flag & PROP_ENUM_NO_CONTEXT) ||
((ptr->type->flag & STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID) &&
(ptr->owner_id == NULL));
if (C != NULL || no_context) {
const EnumPropertyItem *item;
if (prop->flag & PROP_ENUM_NO_CONTEXT) {
item = eprop->item_fn(NULL, ptr, prop, r_free);
}
else {
item = eprop->item_fn(C, ptr, prop, r_free);
}
item = eprop->item_fn(no_context ? NULL : C, ptr, prop, r_free);
/* any callbacks returning NULL should be fixed */
BLI_assert(item != NULL);
/* any callbacks returning NULL should be fixed */
BLI_assert(item != NULL);
if (r_totitem) {
int tot;
for (tot = 0; item[tot].identifier; tot++) {
/* pass */
if (r_totitem) {
int tot;
for (tot = 0; item[tot].identifier; tot++) {
/* pass */
}
*r_totitem = tot;
}
*r_totitem = tot;
}
*r_item = item;
}
else {
*r_item = eprop->item;
if (r_totitem) {
*r_totitem = eprop->totitem;
*r_item = item;
return;
}
}
*r_item = eprop->item;
if (r_totitem) {
*r_totitem = eprop->totitem;
}
}
void RNA_property_enum_items(bContext *C,
@ -1753,43 +1753,43 @@ void RNA_property_enum_items_gettexted_all(bContext *C,
*r_totitem = eprop->totitem;
}
if (eprop->item_fn && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
const EnumPropertyItem *item;
int i;
bool free = false;
if (eprop->item_fn != NULL) {
const bool no_context = (prop->flag & PROP_ENUM_NO_CONTEXT) ||
((ptr->type->flag & STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID) &&
(ptr->owner_id == NULL));
if (C != NULL || no_context) {
const EnumPropertyItem *item;
int i;
bool free = false;
if (prop->flag & PROP_ENUM_NO_CONTEXT) {
item = eprop->item_fn(NULL, ptr, prop, &free);
}
else {
item = eprop->item_fn(C, ptr, prop, &free);
}
item = eprop->item_fn(no_context ? NULL : NULL, ptr, prop, &free);
/* any callbacks returning NULL should be fixed */
BLI_assert(item != NULL);
/* any callbacks returning NULL should be fixed */
BLI_assert(item != NULL);
for (i = 0; i < eprop->totitem; i++) {
bool exists = false;
int i_fixed;
for (i = 0; i < eprop->totitem; i++) {
bool exists = false;
int i_fixed;
/* Items that do not exist on list are returned,
* but have their names/identifiers NULL'ed out. */
for (i_fixed = 0; item[i_fixed].identifier; i_fixed++) {
if (STREQ(item[i_fixed].identifier, item_array[i].identifier)) {
exists = true;
break;
/* Items that do not exist on list are returned,
* but have their names/identifiers NULL'ed out. */
for (i_fixed = 0; item[i_fixed].identifier; i_fixed++) {
if (STREQ(item[i_fixed].identifier, item_array[i].identifier)) {
exists = true;
break;
}
}
if (!exists) {
item_array[i].name = NULL;
item_array[i].identifier = "";
}
}
if (!exists) {
item_array[i].name = NULL;
item_array[i].identifier = "";
if (free) {
MEM_freeN((void *)item);
}
}
if (free) {
MEM_freeN((void *)item);
}
}
#ifdef WITH_INTERNATIONAL