Fix T90907: RNA pointers for material slots are not unique across IDs

Caused by {rB1a81d268a19f}.

This caused e.g. ALT-clicking the 'Link' button to not propagate to
other selected objects (same as the 'Copy To Selected' context menu
entry).

If these are not unique across IDs, checks in ui_selectcontext_begin()
or copy_to_selected_button() could fail.

Now offset by ID pointer.

thx @JacquesLucke for clarification on the POINTER_* macros (and why
not to use them)!

Maniphest Tasks: T90907

Differential Revision: https://developer.blender.org/D12321
This commit is contained in:
Philipp Oeser 2021-08-25 13:09:44 +02:00
parent 7dba879829
commit 6845aad1a2
Notes: blender-bot 2023-02-13 17:50:16 +01:00
Referenced by issue #90907, Change "Link materials to the object or the object's data" on multiple objects
2 changed files with 8 additions and 6 deletions

View File

@ -987,7 +987,8 @@ int /*eContextResult*/ buttons_context(const bContext *C,
matnr = 0;
}
/* Keep aligned with rna_Object_material_slots_get. */
CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, POINTER_FROM_INT(matnr + 1));
CTX_data_pointer_set(
result, &ob->id, &RNA_MaterialSlot, (void *)(matnr + (uintptr_t)&ob->id));
}
}

View File

@ -1326,8 +1326,8 @@ static int rna_Object_rotation_4d_editable(PointerRNA *ptr, int index)
static int rna_MaterialSlot_index(PointerRNA *ptr)
{
/* There is an offset of one, so that `ptr->data` is not null. */
return POINTER_AS_INT(ptr->data) - 1;
/* There is an offset, so that `ptr->data` is not null and unique across IDs. */
return (uintptr_t)ptr->data - (uintptr_t)ptr->owner_id;
}
static int rna_MaterialSlot_material_editable(PointerRNA *ptr, const char **UNUSED(r_info))
@ -1490,10 +1490,11 @@ static void rna_Object_material_slots_next(CollectionPropertyIterator *iter)
static PointerRNA rna_Object_material_slots_get(CollectionPropertyIterator *iter)
{
PointerRNA ptr;
RNA_pointer_create((ID *)iter->internal.count.ptr,
ID *id = (ID *)iter->internal.count.ptr;
RNA_pointer_create(id,
&RNA_MaterialSlot,
/* Add one, so that `ptr->data` is not null. */
POINTER_FROM_INT(iter->internal.count.item + 1),
/* Add offset, so that `ptr->data` is not null and unique across IDs. */
(void *)(iter->internal.count.item + (uintptr_t)id),
&ptr);
return ptr;
}