Fix #135235: Grease Pencil: Crash when removing layers in python API
When iterating over the layers in a Grease Pencil object, removing the layers can lead to crashes. This PR is a better alternative to !135253. Instead of checking if the layer is valid, simply fetch the latest layer cache for each iteration and check if the index is valid. This means that we will skip over layers if they get removed during iteration, but we no longer can crash. If users want to remove multiple layers at once, it's better to do this in two passes. E.g. by first collecting the names of the layers to remove, iterating over these names and then removing the layers by getting it by its name. Pull Request: https://projects.blender.org/blender/blender/pulls/135574
This commit is contained in:
@@ -309,10 +309,31 @@ static void rna_iterator_grease_pencil_layers_begin(CollectionPropertyIterator *
|
||||
{
|
||||
using namespace blender::bke::greasepencil;
|
||||
GreasePencil *grease_pencil = rna_grease_pencil(ptr);
|
||||
const blender::Span<const Layer *> layers = grease_pencil->layers();
|
||||
|
||||
iter->internal.count.item = 0;
|
||||
iter->valid = !layers.is_empty();
|
||||
}
|
||||
|
||||
static void rna_iterator_grease_pencil_layers_next(CollectionPropertyIterator *iter)
|
||||
{
|
||||
using namespace blender::bke::greasepencil;
|
||||
GreasePencil *grease_pencil = static_cast<GreasePencil *>(iter->parent.data);
|
||||
const blender::Span<const Layer *> layers = grease_pencil->layers();
|
||||
|
||||
iter->internal.count.item++;
|
||||
iter->valid = layers.index_range().contains(iter->internal.count.item);
|
||||
}
|
||||
|
||||
static PointerRNA rna_iterator_grease_pencil_layers_get(CollectionPropertyIterator *iter)
|
||||
{
|
||||
using namespace blender::bke::greasepencil;
|
||||
GreasePencil *grease_pencil = static_cast<GreasePencil *>(iter->parent.data);
|
||||
blender::Span<Layer *> layers = grease_pencil->layers_for_write();
|
||||
|
||||
rna_iterator_array_begin(
|
||||
iter, (void *)layers.data(), sizeof(Layer *), layers.size(), false, nullptr);
|
||||
return RNA_pointer_create_discrete(iter->parent.owner_id,
|
||||
&RNA_GreasePencilLayer,
|
||||
static_cast<void *>(layers[iter->internal.count.item]));
|
||||
}
|
||||
|
||||
static int rna_iterator_grease_pencil_layers_length(PointerRNA *ptr)
|
||||
@@ -642,11 +663,31 @@ static void rna_iterator_grease_pencil_layer_groups_begin(CollectionPropertyIter
|
||||
{
|
||||
using namespace blender::bke::greasepencil;
|
||||
GreasePencil *grease_pencil = rna_grease_pencil(ptr);
|
||||
const blender::Span<const LayerGroup *> groups = grease_pencil->layer_groups();
|
||||
|
||||
iter->internal.count.item = 0;
|
||||
iter->valid = !groups.is_empty();
|
||||
}
|
||||
|
||||
static void rna_iterator_grease_pencil_layer_groups_next(CollectionPropertyIterator *iter)
|
||||
{
|
||||
using namespace blender::bke::greasepencil;
|
||||
GreasePencil *grease_pencil = static_cast<GreasePencil *>(iter->parent.data);
|
||||
const blender::Span<const LayerGroup *> groups = grease_pencil->layer_groups();
|
||||
|
||||
iter->internal.count.item++;
|
||||
iter->valid = groups.index_range().contains(iter->internal.count.item);
|
||||
}
|
||||
|
||||
static PointerRNA rna_iterator_grease_pencil_layer_groups_get(CollectionPropertyIterator *iter)
|
||||
{
|
||||
using namespace blender::bke::greasepencil;
|
||||
GreasePencil *grease_pencil = static_cast<GreasePencil *>(iter->parent.data);
|
||||
blender::Span<LayerGroup *> groups = grease_pencil->layer_groups_for_write();
|
||||
|
||||
rna_iterator_array_begin(
|
||||
iter, (void *)groups.data(), sizeof(LayerGroup *), groups.size(), false, nullptr);
|
||||
return RNA_pointer_create_discrete(iter->parent.owner_id,
|
||||
&RNA_GreasePencilLayerGroup,
|
||||
static_cast<void *>(groups[iter->internal.count.item]));
|
||||
}
|
||||
|
||||
static int rna_iterator_grease_pencil_layer_groups_length(PointerRNA *ptr)
|
||||
@@ -1457,9 +1498,9 @@ static void rna_def_grease_pencil_data(BlenderRNA *brna)
|
||||
RNA_def_property_struct_type(prop, "GreasePencilLayer");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_iterator_grease_pencil_layers_begin",
|
||||
"rna_iterator_array_next",
|
||||
"rna_iterator_array_end",
|
||||
"rna_iterator_array_dereference_get",
|
||||
"rna_iterator_grease_pencil_layers_next",
|
||||
nullptr,
|
||||
"rna_iterator_grease_pencil_layers_get",
|
||||
"rna_iterator_grease_pencil_layers_length",
|
||||
nullptr, /* TODO */
|
||||
nullptr, /* TODO */
|
||||
@@ -1472,9 +1513,9 @@ static void rna_def_grease_pencil_data(BlenderRNA *brna)
|
||||
RNA_def_property_struct_type(prop, "GreasePencilLayerGroup");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_iterator_grease_pencil_layer_groups_begin",
|
||||
"rna_iterator_array_next",
|
||||
"rna_iterator_array_end",
|
||||
"rna_iterator_array_dereference_get",
|
||||
"rna_iterator_grease_pencil_layer_groups_next",
|
||||
nullptr,
|
||||
"rna_iterator_grease_pencil_layer_groups_get",
|
||||
"rna_iterator_grease_pencil_layer_groups_length",
|
||||
nullptr, /* TODO */
|
||||
nullptr, /* TODO */
|
||||
|
||||
Reference in New Issue
Block a user