- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Написание скриптов для Blender 2.49 - Michel Anders
Шрифт:
Интервал:
Закладка:
3. Собрать меш существа из строительных блоков так, как определил пользователь.
4. Вставить меш как объект в сцену.
Мы пройдём через скрипт постепенно, показывая важные части в подробностях. (Полный скрипт доступен как creepycrawlies.py.) Первый шаг включает создание частей тела, которые пригодны для сборки вместе. Это означает, что мы должны смоделировать эти части в Блендере, определяя подходящее соединение и отмечая это соединение как группу вершин. Затем мы экспортируем эти меши в виде кода на Питоне, используя скрипт, с которым мы столкнёмся снова в следующей главе, поскольку она имеет дело с группами вершин.
Сейчас мы используем этот сгенерированный код на Питоне просто как модуль, содержащий несколько списков вершин, определяющих каждую часть тела. Мы должны убедиться, что этот модуль находится где-нибудь в пути поиска Питона, например, .blenderscriptsbpymodules будет логичным выбором, или это может быть альтернативный пользовательский каталог скриптов. Файл на Питоне с мешевыми строительными блоками называется mymesh.py, так что первая часть нашего кода содержит следующий оператор import:
import mymesh
Создание пользовательского интерфейсаПри рисовании простого интерфейса пользователя материалом будет использование Draw.Create() для создания необходимых кнопок, и сборка и инициализация этих кнопок с Draw.PupBlock()
Это несколько ограниченно по сравнению со вполне оперившимися библиотеками, доступными для некоторых языков программирования, но очень легко для использования. Основная идея в том, чтобы создать интерактивные объекты, такие, как например, кнопки, затем собрать их в окне диалога, чтобы показать пользователю. В то же самое время, окно диалога задаёт некоторые ограничения на величины, которые кнопка может порождать. Диалог или выпадающее меню будет показываться в позиции курсора. Блендер способен воспроизводить более сложный интерфейс пользователя, но пока мы придерживаемся основ.
Хотя Draw.Create() может воспроизвести кнопки-переключатели, а также кнопки ввода строк, для нашего приложения нам нужны только кнопки ввода для целых величин и величин с плавающей точкой. Тип переменной (например величина с плавающей точкой или целое), определяется типом значения по умолчанию, передаваемого в Draw.Create(). Кнопка OK будет автоматически отображена функцией Draw.PupBlock(). Эта функция берет список кортежей как аргумент, где каждый кортеж определяет кнопку для отображения. Каждый кортеж состоит из текста, отображаемого на кнопке, объекта кнопки, созданного функцией Draw.Create(), допустимых минимума и максимума величины, и текста подсказки (tooltip), появляющегося при наведении курсора на кнопку.
Draw = Blender.Draw
THORAXSEGMENTS = Draw.Create(3) # Сегментов в торсе
TAILSEGMENTS = Draw.Create(5) # Сегментов в хвосте
LEGSEGMENTS = Draw.Create(2) # Сегментов торса с
# ногами
WINGSEGMENTS = Draw.Create(2) # Сегментов торса с
# крыльями
EYESIZE = Draw.Create(1.0) # Размер глаз
TAILTAPER = Draw.Create(0.9) # Конусность каждого
сегмента хвоста
if not Draw.PupBlock('Add CreepyCrawly', [
('Thorax segments:' , THORAXSEGMENTS, 2, 50,
'Number of thorax segments'),
('Tail segments:' , TAILSEGMENTS, 0, 50, 'Number of tail
segments'),
('Leg segments:' , LEGSEGMENTS, 2, 10,
'Number of thorax segments with legs'),
('Wing segments:' , WINGSEGMENTS, 0, 10,
'Number of thorax segments with wings'),
('Eye size:' , EYESIZE, 0.1,10, 'Size of the eyes'),
('Tail taper:' , TAILTAPER, 0.1,10,
'Taper fraction of each tail segment'),]):
return
Как Вы можете видеть, мы ограничиваем возможные величины наших кнопок ввода в разумном диапазоне (вплоть до 50 для сегментов торса и хвоста), чтобы исключить нежелательные результаты (огромные величины могут обрушить вашу систему, если память или процессорная мощность скудны).
Запоминание выбораБыло бы очень удобно, если бы мы могли запоминать выбор пользователя, чтобы можно было выставить последние настройки, когда скрипт заработает снова, но в Блендере каждый скрипт запускается изолированно, и вся информация внутри скрипта теряется, как только он завершится. Следовательно, нам нужен некоторый механизм, сохраняющий информацию в постоянном режиме. С этой целью, API Блендера имеет модуль Registry (Реестра), который позволяет нам сохранять величины в памяти (а также на диске), индексируемые произвольным ключом.
Наш код инициализации GUI изменится немного по своей сути, если мы хотим добавить эту функциональность, но мы покажем код, извлекающий запомненные значения (если они существуют), и сопроводим код, сохраняющий выборы пользователя:
reg = Blender.Registry.GetKey('CreepyCrawlies',True)
try:
nthorax=reg['ThoraxSegments']
except:
nthorax=3
try:
ntail=reg['TailSegments']
except:
ntail=5
... <подобный код для остальных параметров> …
Draw = Blender.Draw
THORAXSEGMENTS = Draw.Create(nthorax)
TAILSEGMENTS = Draw.Create(ntail)
LEGSEGMENTS = Draw.Create(nleg)
WINGSEGMENTS = Draw.Create(nwing)
EYESIZE = Draw.Create(eye)
TAILTAPER = Draw.Create(taper)
if not Draw.PupBlock('Add CreepyCrawly', [
... <идентичный код, как в предыдущем примере> …
return
reg={'ThoraxSegments':THORAXSEGMENTS.val,
'TailSegments' :TAILSEGMENTS.val,
'LegSegments' :LEGSEGMENTS.val,
'WingSegments' :WINGSEGMENTS.val,
'EyeSize' :EYESIZE.val,
'TailTaper':TAILTAPER.val}
Blender.Registry.SetKey('CreepyCrawlies',reg,True)
Фактические чтение и запись нашего ключа в реестре выделены. Аргумент True (Истина) указывает, что мы хотим извлечь наши данные с диска, если они не доступны в памяти, или записать их на диск также при сохранении, чтобы наш скрипт мог иметь доступ к этой сохраненной информации, даже если мы останавливали Блендер и перезапустили его позже. Фактически получаемый или записываемый ключ реестра - это словарь, который может содержать любые данные, которые нам нужны. Конечно, к настоящему времени ключа реестра может еще не существовать, в этом случае мы получим значение None (Ничто) - об этой ситуации заботится оператор try … except … .
Вся мощь графики БлендераВсплывающий диалог достаточен для многих применений, но если он не соответствует вашим требованиям, модуль Блендера Draw имеет множество строительных блоков для создания интерфейса пользователя, но эти строительные блоки требуют больше усилий, чтобы склеить их вместе в рабочем приложении.
Мы используем это построение из блоков, чтобы создать всплывающее сообщение об ошибке. Это всплывающее окно просто показывает сообщение на тревожном цветном фоне, но хорошо иллюстрирует, как действия пользователя (например, нажатия клавиш или кнопок мыши) связаны с графическими элементами.
from Blender import Window,Draw,BGL
def event(evt, val):
if evt == Draw.ESCKEY:
Draw.Exit() # exit when user presses ESC
return
def button_event(evt):
if evt == 1:
Draw.Exit()
return
def msg(text):
w = Draw.GetStringWidth(text)+20
wb= Draw.GetStringWidth('Ok')+8
BGL.glClearColor(0.6, 0.6, 0.6, 1.0)
BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
BGL.glColor3f(0.75, 0.75, 0.75)
BGL.glRecti(3,30,w+wb,3)
Draw.Button("Ok",1,4,4,wb,28)
Draw.Label(text,4+wb,4,w,28)
def error(text):
Draw.Register(lambda:msg(text), event, button_event)
В функции error() все начинается и заканчивается для пользователя; она сообщает Блендеру что рисовать, куда посылать события, такие, как щелчки по кнопке, куда послать нажатую клавишу, и начинает взаимодействие. Лямбда-функция необходима как функция, которую мы передаем в Draw.Register(), которая рисует, но не принимает аргументов, в то время как мы хотим передавать разные аргументы text каждый раз, когда мы вызываем error(). Функция lambda по существу определяет новую функцию без аргументов, но с вложенным текстом.
Функция msg() отвечает за отрисовку всех элементов на экране. Она рисует цветной фон с помощью функции BGL.glRecti(), сообщение с текстом для отображения (с Draw.Label()), и кнопку OK, которой назначается событие номер 1 (с Draw.Button()). Когда пользователь щелкает по кнопке OK, этот номер события посылается в обработчик событий (event handler) - функцию button_event(), которую мы передали в Draw.Register(). Все, что обработчик событий делает, когда он вызывается с этим номером события 1 - завершает функцию Draw.Register() вызовом Draw.Exit(), так что наша функция error() может завершиться.