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 scene.collection.objects.link(obj) # Add the skin modifier 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.