Выбрать главу

try:

    verts = me.getVertsFromGroup(idprop['VertexGroup'])

except AttributeError:

    verts = range(len(me.verts))

for vi in verts:

    d = (me.verts[vi].co+delta_ob).length

    if d < smallest :

        smallest = d

        si = vi

    obloc = me.verts[si].co+tloc

    vnormal = me.verts[si].no

Примечание занудного и наглого переводчика Striver'а

Конструкция try/except гарантирует, что если свойство VertexGroup ссылается на несуществующую группу вершин, мы получим шанс проверить все вершины. Конечно, нам теперь нужен способ для пользователя, позволяющий выбирать группу вершин, так что функцию getSettings() нужно тоже адаптировать. Мы довольствуемся простым полем ввода строки, где можно набрать имя группы вершин. Нет проверки на существование группы, и если мы не хотим ограничиваться привязкой к группе вершин, тогда мы можем или оставить это поле ввода пустым, или занести имя несуществующей группы. Не слишком изящно, но это работает (дополнительные строки выделены):

def getSettings(idprop):

    if not idprop.has_key('VertexGroup'):

       idprop['VertexGroup'] = 'Zone'

    if not idprop.has_key('NormalAlign'):

       idprop['NormalAlign'] = True

    vgroup = Draw.Create(idprop['VertexGroup'])

    align = Draw.Create(idprop['NormalAlign'])

    block = []

    block.append("Additional restrictions: ")

    block.append(("Vertex Group: ",vgroup,0,30,"Vertex

                   Group to restrict location to"))

    block.append(("Alignment: ",align,

                  "Align along vertex normal"))

    retval = Draw.PupBlock("Zoning Constraint", block)

    if (retval):

        idprop['VertexGroup']= vgroup.val

        idprop['NormalAlign']= align.val

Следующий скриншот показывает, как может выглядеть поле ввода для группы вершин:

Заметьте, что скриптовое ограничение также обеспечивает пользователя полем ввода строки VG, которая может ссылаться на группу вершин, но это отличается от поля ввода группы вершин, которую мы показываем пользователю во всплывающих Опциях. Это поле VG будет изменять способ рассматривания ограничением цели. Если здесь задаётся корректная группа вершин, целевая матрица передаваемая в doConstraint(), будет усреднённой позицией вершин в вершинной группе.

Итог

В этой главе мы увидели как различные свойства анимации могут связываться вместе, и как мы можем ограничивать пространственные свойства объектов сложными ограничениями. Мы узнали как:

• Управлять одним IPO из другого посредством выражения на Питоне

• Обходить некоторые ограничения, присущие управляющим объектам

• Ограничивать движение объектов и костей, добавляя ограничения (constraints)

• Писать ограничение на Питоне, которое привязывает объект к ближайшей вершине на другом объекте

Затем мы взглянем на то, как выполнять некоторое действие всякий раз, когда мы передвигаемся по кадрам в нашей анимации.

5

Действия при изменениях кадров

Кроме тех многих мест, с которыми мы столкнулись, где Питон может быть использован в Блендере, мы теперь посмотрим на скрипты, которые можно использовать для действия при определенных событиях. В этот тип скриптов входят две изюминки - скриптсвязи и обработчики пространства.

Скриптсвязи (Script links) являются скриптами, которые могут быть ассоциированы с объектами Блендера (Меши, Камеры, и так далее, а также Сцены и объекты Мира), и их можно настроить так, чтобы они автоматически срабатывали в следующих случаях:

• Сразу перед рендером кадра

• Сразу после рендера кадра

• Когда кадр сменяется

• Когда объект скорректирован

• Когда данные объекта скорректированы

Объекты Сцены можно связать с ассоциированными с ними скриптами, которые могут вызываться в двух дополнительных случаях:

• При загрузке .blend файла

• При сохранении .blend файла

Обработчики пространства (Space handlers) являются скриптами на Питоне, которые вызываются всякий раз, когда окно 3D-вида перерисовывается или обнаружено действие клавиатуры или мыши. Их основным применением является расширение возможностей интерфейса пользователя Блендера.