Одним из условий комфортной работы является удобство и быстрота обращения к функционалу аддона. Недостаточно просто написать аддон и зарегистрировать его в системе. Обязательно нужно предоставить пользователю возможность легко и просто вызывать его функции, а значит, любой аддон должен определять место для размещения кнопок, предоставляющих доступ к собственному функционалу.
Весь доступный интерфейс пользователя Blender располагается на панелях, три из которых используются в работе чаще всего. Это T-панель – открывается и скрывается по нажатию клавиши t, N-панель – открывается и скрывается по нажатию на клавишу n, и панель свойств Properties – вызывается в главном меню любого окна выбором его типа как Properties.
API Blender предоставляет возможность определить свою пользовательскую панель для размещения кнопок вызова функционала аддона в любой из этих главных панелей.
Рассмотрим размещение кнопок вызова функционала на примере простейшего демонстрационного аддона, который добавляет в сцену куб. Тот самый дефолтный куб, должна же от него быть хоть какая-то польза ).
Код такого аддона выглядит следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
bl_info = { 'name': 'Creating panels demonstation', 'category': 'All' } import bpy class addCubeSample(bpy.types.Operator): bl_idname = 'mesh.add_cube_sample' bl_label = 'Add Cube' bl_options = {"REGISTER", "UNDO"} def execute(self, context): bpy.ops.mesh.primitive_cube_add() return {"FINISHED"} def register() : bpy.utils.register_class(addCubeSample) def unregister() : bpy.utils.unregister_class(addCubeSample) |
В данном примере мы взяли системный оператор bpy.ops.mesh.primitive_cube_add() и обернули его вызов в собственный класс, сделав его собственным оператором.
Функционал уже нашего оператора можно вызывать, открыв окно Python Console и набрав команду bpy.ops.mesh.add_cube_sample(). Но, конечно, это неудобно.
Добавим в каждую из основных панелей Blender собственные панели, на которых разместим кнопки вызова нашего аддона. Всего создадим 4 панели – две в разных областях T-панели, одну в N-панели и одну в одной из вкладок окна Properties – вкладке Render.
Как и пользовательские операторы, панели в API Blender создаются в форме классов. Классы панелей необходимо наследовать от bpy.types.Panel.
Внутри класса панели необходимо переопределить родительскую функцию draw, которая отвечает за вывод панели. Функция draw выполняется в момент регистрации класса функцией register_class. Внутри функции draw необходимо заполнить объект layot структурой выводимого на панель интерфейса: кнопками, полями, переключателями, всем тем, что нужно для работы аддона.
В момент завершения работы (отключения аддона) зарегистрированные классы панелей, как и операторы, должны удаляться из API функцией unregister_class.
Как и для операторов, внутри класса панели необходимо определить константу – идентификатор класса с предопределенным именем bl_idname. Текстовая переменная bl_label служит для хранения текста с заголовком панели.
Для определения места, где будет располагаться панель в интерфейсе Blender служат еще несколько переменных с предопределенными именами, которые нужно определить внутри класса панели:
- bl_space_type
- Указывает на пространство (по сути – на окно), где будет расположена панель. Может принимать следующие значения: EMPTY, VIEW_3D, TIMELINE, GRAPH_EDITOR, DOPESHEET_EDITOR, NLA_EDITOR, IMAGE_EDITOR, SEQUENCE_EDITOR, CLIP_EDITOR, TEXT_EDITOR, NODE_EDITOR, LOGIC_EDITOR, PROPERTIES, OUTLINER, USER_PREFERENCES, INFO, FILE_BROWSER, CONSOLE.
- bl_region_type
- Указывает регион внутри пространства, в котором будет размещаться панель. Может принимать значения: WINDOW, HEADER, CHANNELS, TEMPORARY, UI, TOOLS, TOOL_PROPS, PREVIEW.
- bl_context
- Указывает контекст размещения панели.
- bl_category
- Указывает на группу размещения панели.
Пользуясь перечисленными правилами создадим 4 класса для размещения пользовательских панелей в нужных местах. На всех панелях выведем одну кнопку, привязанную к вызову созданного ранее оператора с идентификатором add_cube_sample.
- T-панель, область инструментов:
Для bl_space_type укажем пространство ‘VIEW_3D’ – окно 3D View. Регионом служит Т-панель, область инструментов, поэтому в bl_region_type укажем ‘TOOLS’. Если размещать нашу панель на одной из уже имеющихся системных вкладок, в качестве категории нужно указать эту вкладку, например ‘Tools’ – верхняя вкладка Tools с кнопками основных инструментов моделирования. Или же можно создать свою вкладку, если указать не предопределенное значение категории.
Класс требуемой панели выглядит следующим образом:
1 2 3 4 5 6 7 8 9 10 |
class panel1(bpy.types.Panel): bl_idname = "panel.panel1" bl_label = "Panel1" bl_space_type = "VIEW_3D" bl_region_type = "TOOLS" # bl_category = "Tools" bl_category = "Panel1" def draw(self, context): self.layout.operator("mesh.add_cube_sample", icon='MESH_CUBE', text="Add Cube 1") |
- T-панель, область свойств:
Все так же, как и для области инструментов T-панели, только в качестве региона нужно указать ‘TOOLS_PROPS’. Категорию указывать не нужно.
1 2 3 4 5 6 7 8 |
class panel2(bpy.types.Panel): bl_idname = "panel.panel2" bl_label = "Panel2" bl_space_type = "VIEW_3D" bl_region_type = "TOOL_PROPS" def draw(self, context): self.layout.operator("mesh.add_cube_sample", icon='MESH_CUBE', text="Add Cube 2") |
- N-панель
Регион – ‘UI’.
1 2 3 4 5 6 7 8 |
class panel3(bpy.types.Panel): bl_idname = "panel.panel3" bl_label = "Panel3" bl_space_type = "VIEW_3D" bl_region_type = "UI" def draw(self, context): self.layout.operator("mesh.add_cube_sample", icon='MESH_CUBE', text="Add Cube 3") |
- Окно Properties, для примера используем вкладку Render.
Пространство – ‘PROPERTIES’, регион – ‘WINDOW’, а чтобы определить вкладку, нужно указать контекст – ‘render’ (строчными буквами).
1 2 3 4 5 6 7 8 9 |
class panel4(bpy.types.Panel): bl_idname = "panel.panel4" bl_label = "Panel4" bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "render" def draw(self, context): self.layout.operator("mesh.add_cube_sample", icon='MESH_CUBE', text="Add Cube 4") |
Классы для панелей готовы. Для того, чтобы панели корректно создавались и удалялись в момент инициализации аддона и при его завершении, проведем их регистрацию внутри функции register и разрегистрацию в unregister.
1 2 3 4 5 6 7 8 9 10 11 |
def register() : bpy.utils.register_class(panel1) bpy.utils.register_class(panel2) bpy.utils.register_class(panel3) bpy.utils.register_class(panel4) def unregister() : bpy.utils.unregister_class(panel1) bpy.utils.unregister_class(panel2) bpy.utils.unregister_class(panel3) bpy.utils.unregister_class(panel4) |
Демонстрационный аддон готов. Если его установить и активизировать, в определенных нами местах будут созданы панели с кнопкой вызова оператора создания куба.
Полный текст демонстрационного аддона:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
bl_info = { 'name': 'Creating panels demonstation', 'category': 'All' } import bpy class addCubeSample(bpy.types.Operator): bl_idname = 'mesh.add_cube_sample' bl_label = 'Add Cube' bl_options = {"REGISTER", "UNDO"} def execute(self, context): bpy.ops.mesh.primitive_cube_add() return {"FINISHED"} class panel1(bpy.types.Panel): bl_idname = "panel.panel1" bl_label = "Panel1" bl_space_type = "VIEW_3D" bl_region_type = "TOOLS" # bl_category = "Tools" bl_category = "Panel1" def draw(self, context): self.layout.operator("mesh.add_cube_sample", icon='MESH_CUBE', text="Add Cube 1") class panel2(bpy.types.Panel): bl_idname = "panel.panel2" bl_label = "Panel2" bl_space_type = "VIEW_3D" bl_region_type = "TOOL_PROPS" def draw(self, context): self.layout.operator("mesh.add_cube_sample", icon='MESH_CUBE', text="Add Cube 2") class panel3(bpy.types.Panel): bl_idname = "panel.panel3" bl_label = "Panel3" bl_space_type = "VIEW_3D" bl_region_type = "UI" def draw(self, context): self.layout.operator("mesh.add_cube_sample", icon='MESH_CUBE', text="Add Cube 3") class panel4(bpy.types.Panel): bl_idname = "panel.panel4" bl_label = "Panel4" bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "render" def draw(self, context): self.layout.operator("mesh.add_cube_sample", icon='MESH_CUBE', text="Add Cube 4") def register() : bpy.utils.register_class(addCubeSample) bpy.utils.register_class(panel1) bpy.utils.register_class(panel2) bpy.utils.register_class(panel3) bpy.utils.register_class(panel4) def unregister() : bpy.utils.unregister_class(addCubeSample) bpy.utils.unregister_class(panel1) bpy.utils.unregister_class(panel2) bpy.utils.unregister_class(panel3) bpy.utils.unregister_class(panel4) if __name__ == "__main__" : register() |
Как такую панель сделать и чтоб она сочетанием клавиш открывалась https://uploads.disquscdn.com/images/bd74fb15cdc5e26516dcbd4a376bdf9608076dd29609cde68fd33c578978f76d.png
С таким на практике не сталкивался. Но момент интересный, попробую разобраться, как будет свободное время. Если разберусь – обязательно напишу.
https://b3d.interplanety.org/sozdanie-plavayuschey-paneli-v-addonah-blender/
https://b3d.interplanety.org/sozdanie-plavayuschey-paneli-v-addonah-blender/