Автор Тема: Совсем не страшный питон.  (Прочитано 17386 раз)

Оффлайн LanuHum

  • Житель
Совсем не страшный питон.
« : 03 Ноябрь 2014, 23:02:27 »
Многие думают, что для того, чтобы мало помалу начать писать скрипты, нужно очень много изучить теории.
Сам я мало знаю теории, далеко не ас в программировании, как некоторые из присутствующих здесь на сайте, но кое-что могу и другим могу показать.
Питон в блендере - это не страшное животное, и его изучение может стать весьма интересным и полезным.
Итак, для начала вооружимся несколькими основными понятиями в языке программирования Python.

1. Код в обязательном порядке пишется на латинице за исключением названий объектов, материалов, текстур и прочих имён.

2. Всё, что пишется на одной строке после символа "#" - комментарий, который так же может быть написан на любом языке.
 Комментарий для исполнения программы не нужен. Его вы оставляете, чтобы помнить, зачем та или иная часть кода.

3. Переменные.
Это то, что несёт информацию от пользователя и применяется для вычислений.
Значения их могут меняться по ходу пьесы.
Переменная должна быть объявлена до действий над ней.(Чуть ниже в п 6.1 это будет понятно)
Пример переменных:
Код
a = 10          # Целое число
b = "Cube"      # Строка
c = 10.0        # Число с плавающей запятой
с = float(a)    # Превращает целое число в число с плавающей запятой
a = int(c)      # Округляет число с плавающей запятой до целого числа

4. Арифметика.
Код
d = a / c   # Разделить
e = a * c   # Умножить
g = a + c   # Сложить
h = a - c   # Вычесть
i = a ** c  # а возвести в степень с

5. Отступы. Если строчка заканчивается символом ":" (двоеточием), то начало следующей строчки должно быть смещено от начала строчки,
 в которой находится символ ":" на четыре отступа вправо.
Пример:
Код
if a > b:
    break
Это так же относится и к строчкам имеющим комментарий.
Пример:
Код
if a > b: # если a > b, то прекращаем цикл
    break

6. Ключевые слова. Это служебные слова, которые нельзя применять в обозначениях переменных.
В текстовом редакторе Блендера есть кнопка, включающая подсветку синтаксиса.
Если вы напишете
Код
k = a * g  
а ниже напишете
Код
float = i / e
то увидите, что float отличается цветом от k. Это значит, что слово float ключевое, и его необходимо заменить на любое другое, не отличающееся цветом от k

6.1 Ключевые слова if, elif, else, or, and задают условия. Часто при этом используются сравнения. Заданное условие заканчивается двоеточием
Код
c = 0 # Вспоминаем пункт 3 и заблаговременно объявляем переменные
g = 6
m = 100
if a == b:                  # Задаём условие: если (if) a равно(==) b 
    c = 1                   # То с равно(=) одному (не забываем про отступ и не путаем равенство со сравнением:
                            # если сравниваем, то ==, если присваиваем значение переменной, то =)   
elif a != b and b > 0:      # Продолжаем задавать условие: или если (elif) a не равно(!=) b и(and) b больше(>) нуля(0)
    с = 2                   # То с равно двум (не забываем про отступ)
elif a < g or a > m:        # Продолжаем задавать условие: или если (elif) a меньше(<), чем g или(or) а больше(>) чем m
    c = 3                   # То с равно трём  (не забываем про отступ)
else:                       # В противном случае, если ни одно условие не удовлетворилось (else)
    c = 4               # То с равно четырём
 
 
Другие сравнения:
a <= b    # а меньше или равно
a >= b    # а больше или равно

6.2 Ключевые слова for, in, range, break
Если нужно выполнить несколько однотипных действий запускается цикл.
Пример:
Код
a = 4
b = a ** 3
c = 5
for i in range(a,b):    # ключевое слово for запускает цикл: по порядку от а до b (i здесь переменная, значение которой с каждым проходом увеличивается на 1)
    с = (с + 3) / i           # к с прибавить 3 и разделить это на i
Понятно, что первый раз с будет равно (5 + 3)/4, то бишь 2, второй раз с будет равно (2 + 3)/5, то бишь 1, третий раз (1 + 3)/6, то бишь 0,666666666667 и так далее...
Код
a = 4
b = a ** 3
c = 5
for i in range(a,b):    # ключевое слово for запускает цикл: по порядку от а до b (i здесь переменная, значение которой с каждым проходом увеличивается на 1)
    с = (с + 3) / i           # к с прибавить 3 и разделить это на i
    if c == 0.001:
        break     # Прекратить цикл
7. Подключаемые модули. Сегодня random и bpy
Код
import random
a = random.random()         # Для переменной а генерируется случайное значение от нуля до одного
a = random.randint(1,10)    # Для переменной а генерируется случайное целое значение от одного до десяти

На первый раз мы много узнали и ничего не поняли бы, если бы не узнали кое-что про наш родной модуль bpy, связывающий Блендер с Питоном
Итак, первая заветная строчка нашего первого скрипта - это подключение нашего родимого модуля
Код
import bpy
Активные элементы -
Код
bpy.context
Определяем нужные так:
Код
scn = bpy.context.scene
ob = bpy.context.object
Из вышесказанного понимаем, что scn и ob - это переменные, а называем мы их так, чтобы приблизительно помнить, что есть что
Варианты sc, sce, obj, да какие угодно
Важно знать, что многие манипуляции над объектами производятся когда они либо активны
Код
scn.objects.active = ob
либо выделены
Код
ob.select = True
Напротив, чтобы объект остался нетронутым с него неплохо было бы снять выделение:
Код
ob.select = False
Создадим стенку из кирпичей, не используя array, чтобы кирпичи легли с небольшой неравномерностью.
Для этого поищем нужные операторы пройдя в меню Help > Operator Cheat Sheet. Кликнув,
мы создадим текстовой блок, который сможем отыскать в текстовом редакторе Блендера.
В строчках, начинающихся с bpy.ops поищем что-нибудь про bpy.ops.object и bpy.ops.transform. Ура! Здесь всё есть, что нам нужно!
Пишем скрипт зная, что у операторов Блендера переменные в скобках - по умолчанию, поэтому употребляем их, только, если наши значения с ними не совпадают:
Код
import bpy
import random
ob=bpy.context.object
for y in range(0,10):  # Цикл! Десять кирпичей в ряд!
    for z in range(0,5): # Цикл! Пять рядов!
        bpy.ops.object.duplicate(linked=False, mode='TRANSLATION')  # Копируем выделенный объект
        bpy.ops.transform.translate(value=(0, (y*2)+(y/10), (z*2)+(z/10))) # Перемещаем копию первый раз на длину одного кирпича плюс шов, далее на два и так далее...
        if z % 2 != 0:  # Если ряд нечётный
            bpy.ops.transform.translate(value=(0, 1, 0)) # сдвигаем кирпич ещё на полкирпича
        scale=random.randint(1,5)  # Задаём случайный масштаб
        bpy.ops.transform.resize(value=(1-(scale/10), 1, 1)) # Масштабируем по оси X
        angle=random.random()/10   # Задаём случайный угол
        bpy.ops.transform.rotate(value=angle, axis=(1, 1, 1))  # Вращаем по все осям
        obj=bpy.context.object # Определяем активный объект. После копирования им становится новый
        obj.select=False # Снимаем выделение с активного объекта
        bpy.context.scene.objects.active=ob # Делаем активным исходный объект, который мы взялись копировать
        ob.select=True  # Выделяем его, чтобы следующий проход цикла скопировал, именно, его, и от его координат разместил следующую копию

[вложение удалено Администратором]
« Последнее редактирование: 04 Ноябрь 2014, 22:08:57 от LanuHum »

bdancer

  • Гость
Re: Совсем не страшный питон.
« Ответ #1 : 04 Ноябрь 2014, 18:16:36 »
В примере лучше сдвигать кирпичи используя ob.dimensions (который bounding box), иначе придется менять скрипт, подгоняя параметры, если размеры кирпича изменятся:
Код
import bpy
import random

ob = bpy.context.object

obX = ob.dimensions[0]
obY = ob.dimensions[1]
obZ = ob.dimensions[2]

# Цикл! Десять кирпичей в ряд!
for y in range(0,10):
    # Цикл! Пять рядов!
    for z in range(0,5):
        # Копируем выделенный объект
        bpy.ops.object.duplicate(linked=False, mode='TRANSLATION')

        # Перемещаем копию первый раз на длину одного кирпича плюс шов, далее на два и так далее...
        bpy.ops.transform.translate(value=(0.0, y * obY, z * obZ))
       
        # Если ряд нечётный
        if z % 2 != 0:
            # сдвигаем кирпич ещё на полкирпича
            bpy.ops.transform.translate(value=(0.0, obY / 2.0, 0.0))

Оффлайн sungreen

  • ...
  • Житель
  • Kostroma mon amour
    • sungreen.github.io
Re: Совсем не страшный питон.
« Ответ #2 : 04 Ноябрь 2014, 19:12:56 »
... добавлю как этим пользоваться и как это выглядит :)  ...
... вот мувик ...
out 27



ps отец всегда говорил, что кирпич в кладке не главное, раствор - главное, он связывает, он держит ...
Для Кота

Оффлайн LanuHum

  • Житель
Re: Совсем не страшный питон.
« Ответ #3 : 04 Ноябрь 2014, 21:49:45 »
Цитировать
... добавлю как этим пользоваться и как это выглядит :)  ...
Он же не дописал до конца.  :) :) :)
 Там как раз проводится переназначение. Если этого ни сделать, то смещение как раз будет производиться ни от изначального, а от последнего продублированного.

Ну, расскажу сегодня про startswith.
Как нам быть, если нам нужно выделить только копии? Блендер копированным объектам присваивает то же название, но только с числовым индексом. Это очень хорошо, поскольку у Питона есть функция позволяющая сравнивать имена по их первым символам. Как это выглядит, мы увидим на примере созданных кирпичиков.
Давайте теперь снимем фаски на каждом кирпиче так же с небольшими отклонениями от определённой величины.
Теперь context.object нас не спасёт. Мы будем обращаться к общей базе данных
bpy.data.objects

Код
import bpy
import random
scene=bpy.context.scene
bpy.ops.object.select_all(action='DESELECT')  # Обязательно снимаем выделение со всех объектов, чтобы в дальнейшем цикл смог выделять их по одному и обрабатывать.
for ob in bpy.data.objects:    # По объекту в базе данных
    if ob.type == "MESH" and ob.name.startswith("Cube"):  # Если тип объекта Mesh и начало имени объекта "Cube"
        ob.select=True    # Выделяем объект
        scene.objects.active = ob  # Делаем его активным
        bpy.ops.object.mode_set(mode="EDIT")  # Переходим в режим редактирования меша, чтобы получить доступ к фейсам
        delta = 0.03+random.random()/10   # Задаём случайную величину фаски
        bpy.ops.mesh.bevel(offset_type='OFFSET', offset=delta, segments=1, profile=0.5, vertex_only=False)  # Применяем bevel, где назначаем offset
        bpy.ops.object.mode_set(mode="OBJECT")  # Переходим в объектный режим, чтобы дать возможность циклу работать со следующим объектом
        ob.select = False  # Снимаем выделение с объекта, чтобы следующий объект выделился один одинёшенек.
:)


[вложение удалено Администратором]
« Последнее редактирование: 04 Ноябрь 2014, 22:03:41 от LanuHum »

Оффлайн LanuHum

  • Житель
Re: Совсем не страшный питон.
« Ответ #4 : 05 Ноябрь 2014, 21:07:18 »
Ну, вот нам подкинули темку. Попробуем произвести рендер анимации, где анимироваться будут даже слои.
Разумеется, написанного выше будет очень недостаточно.
Нам нужно погуглить и отыскать руководство по пользованию модулем os
Нам нужно подключить аддон api-navigator, что в разделе development. Этот аддон помогает отыскивать пути к крутилкам, которыми мы пользуемся, используя мышку и клавиатуру. При наведении на крутилки вплывают подсказки, указывающие, цели, а навигатор напишет нам правильно путь.
Теперь прикинем, что мы будем писать в операторе:
Код
import os
import bpy
scn=bpy.context.scene
start=scn.frame_start
end=scn.frame_end
format=scn.render.image_settings.file_format.lower()
for i in range(start,end):
    scn.frame_set(i,0.0)
    scn.layers[0]=scn.lay_anim_0
    scn.layers[1]=scn.lay_anim_1
    scn.layers[2]=scn.lay_anim_2
    scn.layers[3]=scn.lay_anim_3
    scn.layers[4]=scn.lay_anim_4
    scn.layers[5]=scn.lay_anim_5
    scn.layers[6]=scn.lay_anim_6
    scn.layers[7]=scn.lay_anim_7
    scn.layers[8]=scn.lay_anim_8
    scn.layers[9]=scn.lay_anim_9
    scn.layers[10]=scn.lay_anim_10
    scn.layers[11]=scn.lay_anim_11
    scn.layers[12]=scn.lay_anim_12
    scn.layers[13]=scn.lay_anim_13
    scn.layers[14]=scn.lay_anim_14
    scn.layers[15]=scn.lay_anim_15
    scn.layers[16]=scn.lay_anim_16
    scn.layers[17]=scn.lay_anim_17
    scn.layers[18]=scn.lay_anim_18
    scn.layers[19]=scn.lay_anim_19
    scn.update()
    bpy.ops.render.render('INVOKE_REGION_WIN')
    image = bpy.data.images["Render Result"]
    filepath = "/tmp/RenderResult_%s.%s"%(i,format)
    if os.path.exists(filepath):
        os.remove(filepath)
    image.save_render(filepath=filepath, scene=None)
А, завтра, попробуем закончить. :)

mr.A

  • Гость
Re: Совсем не страшный питон.
« Ответ #5 : 28 Август 2015, 10:30:58 »
Как настроить автодополнение кода из blender api в среде разработки Eric6. Для этого нужны *.api файлы. Для python эти файлы уже есть, а вот для blender, их естественно нет. Как их сделать:
С программой eric поставляется много всего(даже свой браузер), в том числе скрипт eric6_api который может сам генерировать *.api файлы из заданных исходных файлов или каталога.
Следующая команда сгенерирует файл api:
Код
eric6_api -r -l Python3 -o Blender.api /usr/share/blender/2.75/scripts/startup /usr/share/blender/2.75/scripts/modules /usr/share/blender/2.75/scripts/addons/modules
Вот только не знаю все ли нужное я включил? Или что-то лишнее?

Вот часть из сгенерированного файла Blender.api чтобы было понятно что получается на выходе скрипта:
Код
bpy.utils.test_register?4(mod)
bpy.utils.test_reload?4(mod)
bpy.utils.time_from_frame?4(frame, fps=None, fps_base=None)
bpy.utils.time_to_frame?4(time, fps=None, fps_base=None)
bpy.utils.unregister_manual_map?4(manual_hook)
bpy.utils.unregister_module?4(module, verbose=False)
bpy.utils.unregister_module_call?4(mod)
bpy.utils.user_resource?4(resource_type, path="", create=False)
bpy_extras.anim_utils.bake_action?4(frame_start, frame_end, frame_step=1, only_selected=False, do_pose=True, do_object=True, do_visual_keying=True, do_constraint_clear=False, do_parents_clear=False, do_clean=False, action=None, )
bpy_extras.anim_utils.obj_frame_info?4(obj)
bpy_extras.anim_utils.pose_frame_info?4(obj)
bpy_extras.image_utils._image_load?5(path)
bpy_extras.image_utils._image_load_placeholder?5(path)

Полученный файл Blender.api скопировать куда-нибудь(я скопировал к остальным в /usr/share/qt/qsci/api/python). В настройках eric Редактор-Автозавершение поставить галочку Разрешить автозавершениеРедактор-Автозавершение-QScintilla из документов и файлов api
Редактор-API Поставить галочку Автоматически компилировать файлы api. выбрать сгенерированный файл Blender.api. Компилировать api. Ok
Теперь работает автодополнение.  Горячая клавиша Ctrl+Space.
Возможно я делаю что-то не так или совсем неправильно. Подскажите, если знаете.
 

[вложение удалено Администратором]
« Последнее редактирование: 28 Август 2015, 10:45:29 от mr.A »

Оффлайн sungreen

  • ...
  • Житель
  • Kostroma mon amour
    • sungreen.github.io
Re: Совсем не страшный питон.
« Ответ #6 : 28 Август 2015, 11:05:47 »
>> Как настроить автодополнение кода из blender api в среде разработки Eric6
... нужная вещь ...
Для Кота

mr.A

  • Гость
Re: Совсем не страшный питон.
« Ответ #7 : 28 Август 2015, 11:24:38 »
Как добавить абсолютно все api? Например, bpy.data не подсказывает и не понимает.  Или я что-то не понимаю...


[вложение удалено Администратором]

Оффлайн LanuHum

  • Житель
Re: Совсем не страшный питон.
« Ответ #8 : 28 Август 2015, 19:17:56 »
Как добавить абсолютно все api? Например, bpy.data не подсказывает и не понимает.  Или я что-то не понимаю...
У меня eric6 не собирается.
Я тоже не понимаю, почему ты всё же выбрал Эрика?
Автодополнение кода работает в консоли Блендера. Для изучения API этого вполне достаточно.
Хотя, я не пользуюсь консолью и автодополнением.
И, не уверен, что ты настроишь своего Эрика так, чтобы он смог иметь доступ ко всему API Блендера.
К тому же, API постоянно изменяется. Это происходит не только от версии к версии, но и с каждым подключением - отключением отдельных аддонов, имеющих собственные элементы интерфейса. Ты будешь писать в Эрике завтра, используя сегодняшние файлы *.api, будешь получать ошибку и недоумевать.
И, на скриншоте навигатор обращается к модулю _bpy, но не к bpy



[вложение удалено Администратором]
« Последнее редактирование: 28 Август 2015, 19:48:40 от LanuHum »

mr.A

  • Гость
Re: Совсем не страшный питон.
« Ответ #9 : 28 Август 2015, 20:39:00 »
Я тоже не понимаю, почему ты всё же выбрал Эрика?
В нем удобно PyQt5. Хочу свои программки с гуи. Хотя я его еще не выбрал.
Цитировать
И, на скриншоте навигатор обращается к модулю _bpy, но не к bpy
Так это разные модули?

Оффлайн LanuHum

  • Житель
Re: Совсем не страшный питон.
« Ответ #10 : 28 Август 2015, 20:57:09 »
Так это разные модули?
Я плохо разбираюсь в том, что мне не нужно, но, предполагаю, что модуль _bpy - это С-ишный модуль, к которому обращается Py-модуль bpy


Оффлайн LanuHum

  • Житель
Re: Совсем не страшный питон.
« Ответ #11 : 28 Август 2015, 21:26:16 »
В нем удобно PyQt5. Хочу свои программки с гуи. Хотя я его еще не выбрал.
И, что, работает pyqt5?
https://www.google.ru/?gfe_rd=cr&ei=maLgVeCYCKSdwAPtqrPoBQ#newwindow=1&q=qopenglshaderprogram+could+not+create+shader+program

mr.A

  • Гость
Re: Совсем не страшный питон.
« Ответ #12 : 28 Август 2015, 23:14:04 »
И, что, работает pyqt5?
Да, работает. Это ты какой-то древний баг нашел. И связанный, видимо, с видео-драйверами.

[вложение удалено Администратором]

mr.A

  • Гость
Re: Совсем не страшный питон.
« Ответ #13 : 28 Август 2015, 23:50:16 »
Выполнить какой-нибудь скрипт в блендере не требующий визуального интерфейса можно так:
Код
blender   --background   -noaudio   --python   myscript.py

Например, можно добавть в Geany такую команду сборки, как на картинке.  Оператор print, вызываемый из скрипта, будет печатать в консоль все, что захочется.

[вложение удалено Администратором]

Оффлайн LanuHum

  • Житель
Re: Совсем не страшный питон.
« Ответ #14 : 29 Август 2015, 00:49:16 »
И, что, работает pyqt5?
Да, работает. Это ты какой-то древний баг нашел. И связанный, видимо, с видео-драйверами.
Это нынешний баг с примерами openGL в pyqt5

 


Яметрика

* По форуму

* Рекламный блок

* Последние вложения

1 (1).png
Скачано: 68
Автор: LEXA ANЭGROWND
blender.png
Скачано: 78
Автор: ipv2007
4.png
Скачано: 100
Автор: hiroyukiss
2.png
Скачано: 122
Автор: hiroyukiss

Скачано: 112
Автор: Dilifa12