In most cases, Tools are easiest to activate by clicking on the buttons in the Toolbar (T-Panel). However, when developing an add-on with a custom UI, it may be convenient to transfer the call to the necessary tools to buttons in the user panel.
Let’s create a class for a simple UI panel:
1 2 3 4 5 6 7 8 9 10 11 |
import bpy class TEST_PT_panel(bpy.types.Panel): bl_idname = 'TEST_PT_panel' bl_label = 'USER PANEL' bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_category = 'USER PANEL' def draw(self, context): layout = self.layout |
In its draw() function, we will create one button to activate a tool, for example – the Transform tool.
Using the ToolSelectPanelHelper class, we can get the Transform tool icon identifier to set it on our button.
1 2 3 |
icon_id = ToolSelectPanelHelper._icon_value_from_icon_handle( 'ops.transform.transform' ) |
Now we need to bind the operator call to the button. A tool can be activated in the Blender Python API by calling the wm.tool_set_by_id() operator, passing the identifier of the desired tool in its “name” parameter.
The code might be something like this:
1 2 3 4 5 6 |
op = layout.operator( operator='wm.tool_set_by_id', icon_value=icon_id, text='' ) op.name = 'builtin.transform' |
In general, this code will work. However, some bugs will occasionally occur, for example, buttons in the user panel will not be drawn correctly, or the tool will not be called if the panel is opened from the keyboard, etc.
To avoid these problems, we can wrap the tool call in a custom operator class.
Let’s create the simplest user operator class. In its execute() function, we will place a call of the wm.tool_set_by_id().
1 2 3 4 5 6 7 8 |
class TEST_OT_test_op(bpy.types.Operator): bl_idname = 'test.test_op' bl_label = 'KNIFE' bl_options = {'REGISTER', 'UNDO'} def execute(self, context): bpy.ops.wm.tool_set_by_id(name='builtin.transform') return {'FINISHED'} |
All that remains is to bind a call to our custom operator to the button in the panel class in the draw() function.
1 2 3 4 5 6 7 8 9 10 11 |
def draw(self, context): layout = self.layout layout.scale_y = 2 icon_id = ToolSelectPanelHelper._icon_value_from_icon_handle( 'ops.transform.transform' ) layout.operator( operator='test.test_op', icon_value=icon_id, text='' ) |
And don’t forget to register the panel and operator classes in the Blender Python API.
1 2 |
bpy.utils.register_class(TEST_OT_test_op) bpy.utils.register_class(TEST_PT_panel) |