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

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн 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

 


* По форуму

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

Слежение.jpg
Скачано: 8
Автор: Barabashka
mehanizm-dlya-podemnoy-krovati-mkb-l633670.jpg
Скачано: 17
Автор: СемёнСемёныч
Безымянный.jpg
Скачано: 18
Автор: СемёнСемёныч
bandicam 2017-11-11 20-01-37-777.jpg
Скачано: 15
Автор: An
Снимок.PNG
Скачано: 18
Автор: Samovar