Некоторые операторы в Blender можно вызывать только в той рабочей области, для которой они предназначены.
Если вызывать, например, оператор, предназначенный только для работы в области 3D вьюпорта в Python-консоли, оператор или просто не выполнится:
1 2 3 |
bpy.ops.wm.toolbar() # {'CANCELLED'} |
или вернет сообщение о неверном контексте:
1 2 3 |
bpy.ops.view3d.background_image_add() # RuntimeError: Operator bpy.ops.view3d.background_image_add.poll() failed, context is incorrect |
Однако выполнить операторы в “не родной” рабочей области все же можно. Для этого в любой оператор можно передать первым неявным параметром указание на контекст рабочей области, в которой должен быть выполнен этот оператор. Этот параметр обычно называют “переопределенный контекст”.
Данный метод подходит для Blender версии 3.1 и более ранних. Для версии Blender 3.2 и более поздних необходимо использовать метод temp_override().
Собственно, переопределенный контекст – это словарь с набором элементов, описывающих нужную рабочую область.
Например, для рабочей области 3D вьюпорта переопределенный контекст нужно составить следующим образом:
1 2 3 4 5 6 7 8 9 10 |
import bpy override_context = bpy.context.copy() area = [area for area in bpy.context.screen.areas if area.type == "VIEW_3D"][0] 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 |
Главное здесь – указать нужную рабочую область – area, в нашем случае это область 3D вьюпорта “VIEW_3D”. Конечно, как минимум одна такая рабочая область должна быть открыта в окнах Blender.
Получив структуру переопределенного контекста, можно вызвать оператор, передавая ее первым параметром:
1 |
bpy.ops.wm.toolbar(override_context) |
Полный код, который будет корректно исполняться из текстового редактора Blender:
1 2 3 4 5 6 7 8 9 10 11 12 |
import bpy override_context = bpy.context.copy() area = [area for area in bpy.context.screen.areas if area.type == "VIEW_3D"][0] 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 bpy.ops.wm.toolbar(override_context) |