# How to set skin_root_mark on selected vertices of a skinned mesh generated in Python?

I'm writing a procedural tree generator that creates a mesh consisting of a network of nodes joined by edges, then adds a Skin Modifier. Here is a simple example with just one trunk and one branch:

The Skin Modifier does this:

I get the desired effect if afterwards, via the UI, I select all nodes that represent "joints" between branches and click "Mark Root" on the Skin Modifier.

It also works if I just select the whole mesh and hit "Mark Root", but obviously this is not really correct. But at this point I'll take that.

The Info panel suggests bpy.ops.object.skin_root_mark() and trial and error suggests this works on the selected vertices in Edit Mode. My effort at scripting this produces this error:

    ret = op_call(self.idname_py(), None, kw)
RuntimeError: Operator bpy.ops.object.skin_root_mark.poll() failed, context is incorrect
Error: Python script failed, check the message in the system console


This error is raised by the attempt to switch to Edit mode or, if that is commented out, by the call to skin_root_mark (the latter is the version pasted above). I can't tell from this error message what the underlying issue is, especially as the same error occurs on either of the lines, which seem

The following is a MWE that exemplifies the crash without all the tree-building logic:

import bpy

# Clean up
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete()

verts = [(0, 0, 0), (1, 0, 0)]
edges = [(0, 1)]

# Create the mesh
mesh = bpy.data.meshes.new("TreeMesh")
mesh.from_pydata(verts, edges, [])
mesh.update()
mesh.validate()

# Create Object to hold the mesh and add it to the scene
obj = bpy.data.objects.new('Tree', mesh)
scene = bpy.context.scene

obj.modifiers.new(name="SK", type="SKIN")

# Make sure to deselect everything in the mesh
# (I guess this is overkill but just in case it makes a difference...)
for g in mesh.vertices[:] + mesh.edges[:] + mesh.polygons[:]:
g.select = False

# Select all vertices
for v in mesh.vertices:
v.select=True

# Either of these lines raises the "context is incorrect" exception:
bpy.ops.object.mode_set(mode="EDIT", toggle=False)
bpy.ops.object.skin_root_mark()



As an aside, it's not at all clear to me how skin_root_mark works. What's the intended behaviour if you have nodes selected that belong to multiple objects and / or are affected by multiple Skin Modifiers? It seems like an odd choice to make it a global function rather than, say, a list of vertices attached to each modifier. If anyone can point me to info on the rationale behind this, that would also be very helpful.

• The object is not active so the context (for the last two lines) cannot find on what to operate. Add bpy.context.view_layer.objects.active = obj Mar 14 '20 at 13:33
• and by the way: only one root which corresponds the red circle in the UI. Mar 14 '20 at 13:33
• @lemon That fixed it, thank you! If you make your comment an answer I'll accept. Looks like until now I'd failed to appreciate the distinction between "selected" and "active". Mar 14 '20 at 16:00

As said in comment, the object is not active and that's why the ops failed.

You may use:

bpy.context.view_layer.objects.active = obj


before the ops.

Though you can also without ops:

# Add the skin modifier
obj.modifiers.new(name="SK", type="SKIN")

#Get the skin vertices layers
skin_vertices = obj.data.skin_vertices
#Get the layer
skin_layer = skin_vertices[0]