В большинстве случаев инструменты (Tools) проще всего активировать нажатием на кнопки в панели инструментов (T-панель). Однако при разработке аддона с пользовательским UI, может оказаться удобным перенести вызов нужных инструментов на кнопки в пользовательской панели.
Создадим класс для простейшей панели UI:
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 |
В функции draw() создадим одну кнопку для активации инструмента, например, инструмента трансформации Transform.
При помощи класса ToolSelectPanelHelper получим идентификатор иконки от инструмента Transform.
1 2 3 |
icon_id = ToolSelectPanelHelper._icon_value_from_icon_handle( 'ops.transform.transform' ) |
Теперь нам нужно оформить вызов оператора. Активацию инструмента в Blender Python API можно произвести вызовом оператора wm.tool_set_by_id(), передав в его параметре name идентификатор нужного инструмента.
Код может быть примерно таким:
1 2 3 4 5 6 |
op = layout.operator( operator='wm.tool_set_by_id', icon_value=icon_id, text='' ) op.name = 'builtin.transform' |
В целом, этот вариант будет работать. Однако периодически будут возникать сбои, например, будут некорректно прорисовываться кнопки в пользовательской панели, или инструмент не будет вызываться, если панель открыта с клавиатуры, и т.п.
Для того чтобы избежать этих проблем, можно обернуть вызов инструмента в кастомный класс оператора.
Оформим простейший класс пользовательского оператора. В его функцию execute() поместим вызов инструмента 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'} |
Осталось в классе панели в функции draw() привязать к кнопке вызов нашего кастомного оператора.
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='' ) |
Не забудьте зарегистрировать классы панели и оператора в Blender Python API.
1 2 |
bpy.utils.register_class(TEST_OT_test_op) bpy.utils.register_class(TEST_PT_panel) |