1
$\begingroup$

I am writing an Addon. I have a list of Vectors:

centers = [p.center for p in obj.data.polygons]

In a later section of code, I do the following to a different object:

bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT')

After this return to Object Mode, the earlier list of centers no longer points to anything, and any reference to it causes a segfault.

This is not the only mode change in the code, but the segfault happens only at this one location. The segfault remains even if I operate on centers_copy = centers.copy(). The segfault goes away if I inelegantly cast the Vectors to lists and back:

centers_list = [list(elt) for elt in centers]
centers = [Vector(elt) for elt in centers_list]

What, precisely, is causing this segfault?

Thanks in advance.

$\endgroup$

2 Answers 2

2
$\begingroup$

Use a copy

centers = [p.center.copy() for p in obj.data.polygons]

Similarly for obj.location

>>> C.object.location
Vector((3.3187315464019775, 1.0073195695877075, 7.229274749755859))

>>> v = C.object.location
>>> vc = C.object.location.copy()
>>> C.object.location = (0, 0, 0)
>>> v
Vector((0.0, 0.0, 0.0))

>>> vc
Vector((3.3187315464019775, 1.0073195695877075, 7.229274749755859))

v is a reference to the object location. It is bound to the object. Removing the object and trying to reference v again will lead to a seg fault.

Use v = C.object.location.copy() for an unbound "snapshot" copy. (casting to list and back was doing this too)

Note centers.copy() was still a copy of a list whose items were references to a polygon and hence the mesh.

As pointed out by @MartinZ you can also set the select values in object mode. The foreach_set(prop, values) method is faster than iterating and setting, eg for polygons

>>> me = C.object.data
>>> me.polygons.foreach_set("select", [False] * len(me.polygons))
>>> 
$\endgroup$
2
  • $\begingroup$ Thanks batFINGER. I will start a new habit of using copies of all locations. $\endgroup$
    – Animik
    Commented Mar 20, 2019 at 17:42
  • $\begingroup$ That's really cool. I actually timed it on a high poly object and apparently that is a lot faster, more than 20 times faster to my surprise in my test at least. $\endgroup$ Commented Mar 20, 2019 at 19:01
1
$\begingroup$

That's weird. It crashes Blender when I try to recheck centers valuues in the console after edit mode switch. Must be some bug in the Blenders Python API. You could deselect everything without switching to edit mode. This seems to work:

import bpy

d = bpy.context.object.data

centers = [p.center for p in d.polygons]

for x in [v for v in d.vertices] + [p for p in d.polygons] + [e for e in d.edges]:
    x.select = False

print(centers)
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .