Thomas Larsson - Введение в написание скриптов на Питоне для Блендера 2.5x. Примеры кода
printProp(ob, '["myRnaInt"]')
printProp(ob, '["myRnaFloat"]')
printProp(ob, '["myRnaString"]')
printProp(ob, '["myRnaBool"]')
printProp(ob, '["myRnaEnum"]')
print("%s ID properties" % ob.data)
printProp(ob.data, '["MyIdInt"]')
printProp(ob.data, '["MyIdFloat"]')
printProp(ob.data, '["MyIdString"]')
printProp(ob.data, '["MyIdBool"]')
Этот скрипт выведет следующий текст на терминале.
RNA properties
Cube.myRnaInt does not exist
Cube.myRnaFloat does not exist
Cube.myRnaString does not exist
Cube.myRnaBool does not exist
Cube.myRnaEnum does not exist
<bpy_struct, Object("Cube")> ID properties
Cube["myRnaInt"] = -99
Cube["myRnaFloat"] = 1.0
Cube["myRnaString"] = I am an RNA prop
Cube["myRnaBool"] = 1
Cube["myRnaEnum"] = 2
<bpy_struct, Mesh("Cube.001")> ID properties
Cube.001["MyIdInt"] = 4711
Cube.001["MyIdFloat"] = 666.777
Cube.001["MyIdString"] = I am an ID prop
Cube.001["MyIdBool"] = 1
Если мы восстановим декларации свойств, ID-свойства преобразуются обратно в RNA-свойства.
Вращение костейЭта программа ожидает, что активный объект — это арматура. Она сохраняет угол вращения каждой editbone как свойство соответствующей кости, и в конце выводит величины свойств на терминале. При выполнении с выбранной арматурой на изображении ниже, результат на терминале выглядит следующим образом.
Head 3.1416
Arm_L 1.5708
Leg_R -2.7646
Leg_L 2.7646
Arm_R -1.5708
Torso 3.1416
Заметьте, что величины свойств выражены в радианах. В интерфейсе углы отображаются в градусах, но при доступе из Питона они выражены в радианах. Тем не менее, свойство Roll - это просто некоторая вещественная переменная, и Блендер не знает, что его предполагается использовать как угол.
Для нахождения свойства в интерфейсе пользователя, нам нужно выбрать кость в режиме позы,и затем переключиться в режим редактирования, как показано на изображении.
Этот код действительно несколько полезен для скрипта, который перенастраивает данные, полученные от захвата движения (motion capture). Для того, чтобы делать это правильно, нам нужно знать углы поворота roll. Тем не менее, их нельзя получить, если арматура связана с другим файлом через прокси. Для того, чтобы получить доступ к углу поворота rig.data.edit_bones[name].roll, арматуру нужно переключить в режим редактирования, который не доступен для связанных объектов. Но если скрипт выполнен в файле, где арматура определена, свойство Roll может быть доступно из связанного файла как rig.pose.bones[name].bone["Roll"].
#----------------------------------------------------------
# File bone_roll.py
#----------------------------------------------------------
import bpy
def createBoneRollProps(rig):
if rig.type != 'ARMATURE':
raise NameError("Object not an armature")
# Объект не является арматурой
bpy.context.scene.objects.active = rig
try:
bpy.ops.object.mode_set(mode='EDIT')
editable = (len(rig.data.edit_bones) > 0)
except:
editable = False
rolls = {}
if editable:
for eb in rig.data.edit_bones:
rolls[eb.name] = eb.roll
bpy.ops.object.mode_set(mode='POSE')
for pb in rig.pose.bones:
pb.bone["Roll"] = rolls[pb.name]
else:
try:
bpy.ops.object.mode_set(mode='POSE')
except:
raise NameError("Armature is not posable. Create proxy")
# У арматуры не доступно позирование. Создайте прокси
for pb in rig.pose.bones:
try:
rolls[pb.name] = pb.bone["Roll"]
except:
raise NameError("Create roll props in asset file")
# Создайте свойство roll в файле актива
return rolls
rolls = createBoneRollProps(bpy.context.object)
for (bname, roll) in rolls.items():
print(" %16s %8.4f" % (bname, roll))
Интерфейс
Большинство скриптов должны взаимодействовать с пользователем каким-то способом. Скрипт может вызываться из меню или с помощью кнопки на панели, и он может получать входные данные посредством движков, переключателей, выпадающих меню или полей ввода. Элементы интерфейса пользователя реализованы как классы Питона. В этих заметках обсуждаются два типа элементов интерфейса:
• Панель является классом, производным от bpy.types.Panel. У неё есть свойства и функция draw, которая вызывается каждый раз, когда панель перерисовывается.
• Оператор является классом, производным от bpy.types.Operator. У него есть свойства, функция execute (выполнить), и необязательная функция invoke. Операторы можно зарегистрировать, чтобы они появились в меню. В частности, кнопка является оператором. Когда Вы нажимаете кнопку, вызывается функция execute.
Как панели, так и операторы должны быть зарегистрированы перед тем, как их начать использовать. Самый простой способ зарегистрировать все в файле — это закончить его с вызовом bpy.utils.register_module(__name__).
Интерфейсная часть API, по видимому, менее стабильна, чем другие части, так что код в этом разделе может стать неработоспособным в будущих выпусках.
Панели и кнопкиЭта программа добавляет пять различных панелей к интерфейсу пользователя в разных местах. Каждая панель имеет имя и кнопку. Для всех кнопок используется один и тот же оператор, но текст на кнопке может быть изменён текстовым аргументом. Когда Вы нажимаете кнопку, Блендер выводит приветствие на терминале.
Оператор кнопки может быть вызван без аргументов, как на первой панели:
self.layout.operator("hello.hello")
Блендер затем будет искать оператор со значением bl_idname, равным hello.hello, и установит его на панели. Текст на кнопке устанавливается по умолчанию в его bl_label, то есть, Say Hello. Класс OBJECT_OT_HelloButton имеет также заказное свойство строкового типа (custom property) с именем country (страна). Оно может быть использовано для передачи аргументов кнопке. Если оператор вызывается без аргумента, свойство country устанавливается по умолчанию в пустую строку.
bl_idname должно быть строкой, содержащей маленькие буквы, цифры и подчеркивания, плюс ровно одна точка; hello.hello удовлетворяет этим критериям. За исключением этого, по-видимому, у bl_idname нет никаких ограничений.
Вид и поведение кнопки по-умолчанию могут быть модифицированы. Давайте вызовем кнопку следующим образом:
self.layout.operator("hello.hello", text='Hej').country = "Sweden"
Текст на этой кнопке - Hej, и значение свойства country является "Sweden" (Швеция). Когда мы нажимаем эту кнопку, Блендер выводит в окне терминала.следующее:
Hello world from Sweden!
В конце файла всё регистрируется с помощью вызова
bpy.utils.register_module(__name__)
Наш вновь определенный оператор кнопки можно теперь использовать как любой другой оператор Блендера. Вот сеанс в консоли Питона Блендера:
>>> bpy.ops.hello.hello(country = "USA")
Hello world from USA!
{'FINISHED'}
Другой путь вызвать наш новый оператор — нажать Пробел. Появится селектор со всеми доступными операторами в позиции курсора мыши. Сократите выбор, набрав подстроку bl_label нашего оператора в поле редактирования. Оператор с параметрами по-умолчанию выполнится, и Hello world! будет выведено в окне терминала.
#----------------------------------------------------------
# File hello.py
#----------------------------------------------------------
import bpy
#
# Меню в районе tools
#
class ToolsPanel(bpy.types.Panel):
bl_label = "Hello from Tools"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
def draw(self, context):
self.layout.operator("hello.hello")
#
# Меню в районе toolprops
#
class ToolPropsPanel(bpy.types.Panel):
bl_label = "Hello from Tool props"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOL_PROPS"
def draw(self, context):
self.layout.operator("hello.hello", text='Hej').country = "Sweden"
#
# Меню в районе UI
#
class UIPanel(bpy.types.Panel):
bl_label = "Hello from UI panel"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
def draw(self, context):
self.layout.operator("hello.hello", text='Servus')
#
# Меню в районе окна Properties, контекст объектов
#
class ObjectPanel(bpy.types.Panel):
bl_label = "Hello from Object context"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW" bl_context = "object"