2
$\begingroup$

I'm hoping someone can help me use the 3DView->Edit Mode builtin tool 'spin'. I've extruded a number of vertices and their edges to form a (closed) 2D face. The object is named called 'RocketNozzle'. I want to use Python to 'spin' this face around the z-axis. I can do this manually from the 3DView editor, but am running into problems using Python to script it. The code below shows my current attempt. I'm basing my approach on these two articles:

I know the line with bpy.ops.wm.tool_set_by_id(override_context, name="builtin.spin") is working, because the spin tool is shown active after this line executes.

But I can't get a reference to the active tool back into the script! I think if I can successfully get a reference to the active (spin) tool, that I can set the three properties I want, and then call tool.Execute() ?? to make the spin occur. I just can't seem to get a valid reference to the tool back into the script.

TIA for any help, insights, or links!

# lots of code to get to this point ...

# The object at this point is a two-dimensional face having many vertices/edges that form the outlines of the inner and outer walls of a complex curved surface
# rotate the face around the z-axis
# Select the entire object
bpy.ops.object.mode_set(mode = 'OBJECT')
obj = bpy.data.objects[PartName]
# Go to Edit Mode
bpy.ops.object.mode_set(mode = 'EDIT') 
# Select all of the vertices
bpy.ops.mesh.select_mode(type="VERT")
bpy.ops.mesh.select_all(action = 'SELECT')

# Spin them all around the z-axis
# Select the builtin Spin tool from the Object->Edit menu
# [how to change a tool through the Blender API](https://b3d.interplanety.org/en/how-to-change-current-tool-through-the-blender-python-api/)
# [how to set the active tool](https://blender.stackexchange.com/questions/178959/enable-disable-3d-cursor-tool-properties-from-python)
area = [area for area in bpy.context.screen.areas if area.type == "VIEW_3D"][0]
override_context = bpy.context.copy()
override_context['window'] = bpy.context.window
override_context['screen'] = bpy.context.screen
override_context['area'] = area
override_context['region'] = area.regions[-1]
override_context['scene'] = bpy.context.scene
override_context['space_data'] = area.spaces.active
# Set the active tool to be the spin tool
bpy.ops.wm.tool_set_by_id(override_context, name="builtin.spin")
# Get the active tool
# (https://blender.stackexchange.com/questions/178959/enable-disable-3d-cursor-tool-properties-from-python)
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper

######################
### Manual steps here, 'cause the next line throws an exception
tool = ToolSelectPanelHelper.tool_active_from_context(override_context)
# Using override_context in the line above, throws an exception : 
#    line 710, in tool_active_from_context
#    space_type = context.space_data.type
#    AttributeError: 'dict' object has no attribute 'space_data'
# 
tool = ToolSelectPanelHelper.tool_active_from_context(bpy.context)
# Using bpy.context as shown in the lineabove causes the next line to fail with the message 
#    AttributeError: 'NoneType' object has no attribute 'steps'
tool.steps = 32
tool.angle = 360
tool.axis = [0,0,1]
### Make it spin somehow
tool.Execute()  # not sure if this is correct....
### End area of manual steps
######################

# copy the lines from here to the end and paste them into Blender's Python Console

# remove duplicates again, to ensure the spin did not add any extra unwanted vertices
#  also change the merge distance (make it larger) in case the duplicate vertices from the spin don't quite line up exactly
bpy.ops.mesh.remove_doubles(threshold=0.01, use_unselected=True)

# more code here...

```
$\endgroup$
2

1 Answer 1

0
$\begingroup$

I agree with Ron Jensen's comment. There's no reason to override the spin tool, just invoke it with settings that accomplish your goal. You can replace most of your code with:

# lots of code to get to this point ...

# The object at this point is a two-dimensional face having many vertices/edges that form the outlines of the inner and outer walls of a complex curved surface
# rotate the face around the z-axis
# Select the entire object
bpy.ops.object.mode_set(mode = 'OBJECT')
obj = bpy.data.objects[PartName]
# Go to Edit Mode
bpy.ops.object.mode_set(mode = 'EDIT') 
# Select all of the vertices
bpy.ops.mesh.select_mode(type="VERT")
bpy.ops.mesh.select_all(action = 'SELECT')
bpy.ops.mesh.spin(steps=32, angle=2*pi, center=(0,0,0), axis=(0,0,1))
# remove duplicates again, to ensure the spin did not add any extra unwanted vertices

#  also change the merge distance (make it larger) in case the duplicate vertices from the spin don't quite line up exactly
bpy.ops.mesh.remove_doubles(threshold=0.01, use_unselected=True)

that is, delete everything between

# Spin them all around the z-axis

and

# copy the lines from here to the end and paste them into Blender's Python Console

inclusive and replace them with

bpy.ops.mesh.spin(steps=32, angle=2*pi, center=(0,0,0), axis=(0,0,1))

This has the added bonus that it won't throw exceptions and you can execute it all within the script.

$\endgroup$
1
  • 1
    $\begingroup$ Wonderful, thank you! FWIW, I also needed to import math, and use math.pi in the final script. $\endgroup$ Commented Oct 29, 2021 at 19:02

You must log in to answer this question.

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