Fix T57760: Depsgraph 'object_instances' showing incorrect list of objects.

It appears that Python gets next item before using current one, which
would break our Depsgraph instance iterator (since only current item is
valid there, we use the same memory at each iteration).

Working around that with an ugly ping-pong game between two sets of
iterator data, so that previous one (C RNA-iterator-wise) remains valid
memory for Python to access to.
This commit is contained in:
Bastien Montagne 2018-11-14 17:04:10 +01:00
parent d2dd278c5e
commit b44e6f2b3d
Notes: blender-bot 2023-06-12 00:52:52 +02:00
Referenced by issue #57760, Depsgraph 'object_instances' showing incorrect list of objects
1 changed files with 32 additions and 11 deletions

View File

@ -280,38 +280,59 @@ static PointerRNA rna_Depsgraph_objects_get(CollectionPropertyIterator *iter)
* Contains extra information about duplicator and persistent ID.
*/
/* XXX Ugly python seems to query next item of an iterator before using current one (see T57558).
* This forces us to use that nasty ping-pong game between two sets of iterator data, so that previous one remains
* valid memory for python to access to. Yuck.
*/
typedef struct RNA_Depsgraph_Instances_Iterator
{
BLI_Iterator iterators[2];
DEGObjectIterData deg_data[2];
int counter;
} RNA_Depsgraph_Instances_Iterator;
static void rna_Depsgraph_object_instances_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
iter->internal.custom = MEM_callocN(sizeof(BLI_Iterator), __func__);
DEGObjectIterData *data = MEM_callocN(sizeof(DEGObjectIterData), __func__);
RNA_Depsgraph_Instances_Iterator *di_it = iter->internal.custom = MEM_callocN(sizeof(*di_it), __func__);
DEGObjectIterData *data = &di_it->deg_data[0];
data->graph = (Depsgraph *)ptr->data;
data->flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
DEG_ITER_OBJECT_FLAG_VISIBLE |
DEG_ITER_OBJECT_FLAG_DUPLI;
((BLI_Iterator *)iter->internal.custom)->valid = true;
DEG_iterator_objects_begin(iter->internal.custom, data);
iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
di_it->iterators[0].valid = true;
DEG_iterator_objects_begin(&di_it->iterators[0], data);
iter->valid = di_it->iterators[0].valid;
}
static void rna_Depsgraph_object_instances_next(CollectionPropertyIterator *iter)
{
DEG_iterator_objects_next(iter->internal.custom);
iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
RNA_Depsgraph_Instances_Iterator *di_it = (RNA_Depsgraph_Instances_Iterator *)iter->internal.custom;
/* We need to copy current iterator status to next one beeing worked on. */
di_it->iterators[(di_it->counter + 1) % 2] = di_it->iterators[di_it->counter % 2];
di_it->deg_data[(di_it->counter + 1) % 2] = di_it->deg_data[di_it->counter % 2];
di_it->counter++;
di_it->iterators[di_it->counter % 2].data = &di_it->deg_data[di_it->counter % 2];
DEG_iterator_objects_next(&di_it->iterators[di_it->counter % 2]);
iter->valid = di_it->iterators[di_it->counter % 2].valid;
}
static void rna_Depsgraph_object_instances_end(CollectionPropertyIterator *iter)
{
DEG_iterator_objects_end(iter->internal.custom);
MEM_freeN(((BLI_Iterator *)iter->internal.custom)->data);
MEM_freeN(iter->internal.custom);
RNA_Depsgraph_Instances_Iterator *di_it = (RNA_Depsgraph_Instances_Iterator *)iter->internal.custom;
DEG_iterator_objects_end(&di_it->iterators[0]);
DEG_iterator_objects_end(&di_it->iterators[1]);
MEM_freeN(di_it);
}
static PointerRNA rna_Depsgraph_object_instances_get(CollectionPropertyIterator *iter)
{
BLI_Iterator *iterator = (BLI_Iterator *)iter->internal.custom;
RNA_Depsgraph_Instances_Iterator *di_it = (RNA_Depsgraph_Instances_Iterator *)iter->internal.custom;
BLI_Iterator *iterator = &di_it->iterators[di_it->counter % 2];
return rna_pointer_inherit_refine(&iter->parent, &RNA_DepsgraphObjectInstance, iterator);
}