Python вопросы

Список разделов Blender 3D Плагины

Описание: Обсуждение расширений для Blender
Модератор: exooman

Сообщение #1 Korchy » 21.10.2014, 15:34

Возможно я плохо пока въехал в питон, но не понимаю, почему первый вариант работает, а когда я пытаюсь захендлить метод класса - условие не работает. Может кто подсказать, в чем ошибка?

Вот так - все работает:
Код: Выделить всё
@persistent
def onRenderFinished(scene):
    print("finished")

class Tmp(bpy.types.Operator):
    def execute(self, context):
        global onRenderFinished
        renderCompleteHadler = bpy.app.handlers.render_complete
        if onRenderFinished not in renderCompleteHadler:
            print("===ADD HANDLER===")
            renderCompleteHadler.append(onRenderFinished)
Здесь все нормально, при повторном вызывании скрипта обработчик дважды не добавляется

Если же я пытаюсь сделать так:
Код: Выделить всё
class Tmp(bpy.types.Operator):

    def execute(self, context):
        renderCompleteHadler = bpy.app.handlers.render_complete
        if self.onRenderFinished not in renderCompleteHadler:
            print("===ADD HANDLER===")
            renderCompleteHadler.append(self.onRenderFinished)

    @persistent
    def onRenderFinished(self, scene):
        print("Finished")
Обработчик добавляется каждый раз новый при каждом вызове скрипта и соответственно получается отработка его несколько раз.
Что я делаю не так?
Korchy M
Аватара
Сообщения: 2290



Сообщение #2 Korchy » 21.10.2014, 18:20

И еще вопрос:
если я взываю рендер через
Код: Выделить всё
bpy.ops.render.render(write_still=True)
обработчик отрабатывает без ошибок:
Код: Выделить всё
@persistent
def onRenderFinished(scene):
    objects = bpy.context.scene.objects
    for object in objects:
        for i, l in enumerate(bpy.context.scene.layers):
            if object.layers[i] == True and object.layers[i] == l:
                if object.type == "MESH":
                    bpy.context.scene.objects.active = object
                    bpy.ops.object.mode_set(mode='EDIT')
                    bpy.ops.mesh.mark_freestyle_edge(clear=True)
                    bpy.ops.object.mode_set(mode='OBJECT')
    return

Если же я вызываю рендер через
Код: Выделить всё
bpy.ops.render.render('INVOKE_DEFAULT')
что нужно, чтобы показать процесс рендера, в обработчике на строчке
Код: Выделить всё
bpy.ops.object.mode_set(mode='EDIT')
вылетает ошибка
bpy.ops.object.mode_set.poll() failed, context is incorrect
Почему ломается контекст в этом случае? И как тогда получить правильный контектс?
Korchy M
Аватара
Сообщения: 2290



  • 1

Сообщение #3 Vasilek » 22.10.2014, 10:47

Korchy писал(а):Обработчик добавляется каждый раз новый при каждом вызове скрипта и соответственно получается отработка его несколько раз.
Что я делаю не так?

не знаю как там все внутри работает но если предположить что при каждом обращении блендер создает новый обьект данного класса то все становится понятно... так как метод обьявлен полем класса и так как он тоже является обьектом значит у разных обьектов он будет разным... так что все правильно он делает...

Korchy писал(а):bpy.ops.object.mode_set.poll() failed, context is incorrect
Почему ломается контекст в этом случае? И как тогда получить правильный контектс?

давно не лазил в скрипты для блендера но насколько я помню такая ошибка может возникнуть когда нет активного выделенного обьекта, вернее как это насколько я помню разные понятия зависимые друг от друга обьект может быть выделенным но неактивным но активным и невыделенным он быть не может... честно не помню как решить эту проблему но я определенно с этим сталкивалися так что стоит покопать в этом направлении :)
Vasilek M
Аватара
Откуда: Самара
Сообщения: 251

Сообщение #4 Korchy » 22.10.2014, 14:28

Vasilek,
Vasilek писал(а):если предположить что при каждом обращении блендер создает новый обьект данного класса то все становится понятно
Вот и странно, получается каждый раз создается новый объект класса, а для функции - нет, создается только один раз.

Vasilek писал(а):насколько я помню такая ошибка может возникнуть когда нет активного выделенного обьекта
Так я делаю текущий объект активным. Если перед строчкой, на которой вылезает ошибка
Код: Выделить всё
bpy.ops.object.mode_set(mode='EDIT')
поставить
Код: Выделить всё
print(bpy.context.scene.objects.active)
в консольном окне выводится
Код: Выделить всё
<bpy_strct, object <"Cube">>
и далее ошибка.
Korchy M
Аватара
Сообщения: 2290



  • 1

Сообщение #5 Vasilek » 22.10.2014, 15:12

Korchy писал(а):от и странно, получается каждый раз создается новый объект класса, а для функции - нет, создается только один раз.

так в том то и дело что в первом случае каждый раз это разный метод а во втором это каждый раз один и тот же...

Korchy писал(а):Так я делаю текущий объект активным. Если перед строчкой, на которой вылезает ошибка

я просто не понимаю как можно сделать активным обьект который даже не выделен?

кстати почему
Код: Выделить всё
bpy.ops.object.mode_set(mode='EDIT')
а не
Код: Выделить всё
 bpy.ops.object.editmode_toggle()
Vasilek M
Аватара
Откуда: Самара
Сообщения: 251

Сообщение #6 Korchy » 22.10.2014, 15:57

Vasilek писал(а):так в том то и дело что в первом случае каждый раз это разный метод а во втором это каждый раз один и тот же...
С этого момента поподробнее. Функция - объект. Класс - объект. Если при каждом обращении все объекты пересоздаются, то и функция и класс одинаково должны пересоздаваться. А получается, класс - пересоздается, функция - нет.

Vasilek писал(а):я просто не понимаю как можно сделать активным обьект который даже не выделен?
Я так понимаю, активный и выделенный объекты - это разные вещи. Как бывает активный объект, когда выделено сразу несколько объектов?

Vasilek писал(а):а не
 bpy.ops.object.editmode_toggle()
Без разницы, пробовал и так и так.
Korchy M
Аватара
Сообщения: 2290



Сообщение #7 Vasilek » 22.10.2014, 16:53

Korchy писал(а):Я так понимаю, активный и выделенный объекты - это разные вещи. Как бывает активный объект, когда выделено сразу несколько объектов?
именно так если выделять вручную несколько обьектов то последний выделенный будет активным если примотреться то у него даже цвет выделения отличается...


Korchy писал(а):С этого момента поподробнее. Функция - объект. Класс - объект. Если при каждом обращении все объекты пересоздаются, то и функция и класс одинаково должны пересоздаваться. А получается, класс - пересоздается, функция - нет.

я не совсем понимаю как это происходит в питоне но получается что фунцкция обьявленая вне класса будет статичной... и всегда одной и той же....
Vasilek M
Аватара
Откуда: Самара
Сообщения: 251

Сообщение #8 Korchy » 22.10.2014, 17:39

Vasilek писал(а):именно так если выделять вручную несколько обьектов то последний выделенный будет активным если примотреться то у него даже цвет выделения отличается
Ну так об этом я и говорю. Я делаю объект активным, перед попыткой перехода в режим редактирования, но ошибка все равно вылезает.
Возможно здесь нужно переопределить (override) context
http://www.blender.org/documentation/blender_pyth ... py.ops.html#overriding-context
т.к. окно у меня переключается на показ процесса рендера, а конекст видимо нужен от окна 3д-вида, но я пока не могу понять, как это вообще работает.

Добавлено спустя 40 минут 36 секунд:
Похоже дело именно в переписывании контекста. Если пытаюсь так:
сохраняю в классе:
Код: Выделить всё
self.bl_override = bpy.context.copy()
self.bl_override['area'] = bpy.context.area

а потом при вызове из функции-обработчика
Код: Выделить всё
bpy.ops.object.mode_set(WireframeRender.bl_override, mode='EDIT')
то все нормально, объект переходит в режим редактирования,
однако следующая же строчка (вернуться в обычный режим) выдает ошибку
Код: Выделить всё
bpy.ops.object.mode_set(WireframeRender.bl_override, mode='OBJECT')
enable to execute 'toggle editmode', error changing modes

если пробую следующую строчку без оверрайда - вылезает та же самая ошибка в poll()
Korchy M
Аватара
Сообщения: 2290



Сообщение #9 Korchy » 22.10.2014, 18:34

Полный код на текущий момент, чего я хочу сделать - можно глянуть здесь
https://code.google.com/p/blender-nx/source/browse/trunk/WireframeRender.py
Korchy M
Аватара
Сообщения: 2290



Сообщение #10 Vasilek » 22.10.2014, 22:30

Я если честно не понял что код должен делать :) а вернее не понял чего вы хотите добиться этим кодом :)
Vasilek M
Аватара
Откуда: Самара
Сообщения: 251

Сообщение #11 Korchy » 22.10.2014, 22:36

Vasilek писал(а):Я если честно не понял что код должен делать
Рендерить сцену в режиме "сетка"
Попробуй запустить - увидишь. Код рабочий за исключением подчистки за собой. Для рендера сетки используется freestyle, вот отмеченные под фристайл ребра и не удается потом почистить. В остальном все работает.
Запуск по ctrl+shift+f12
Точнее два варианта - если с показом процесса рендера - почистить за собой не получается. Или вариант - рендер без показа, просто сохраняет результат в файл с проектом - тогда все чистится нормально.
Korchy M
Аватара
Сообщения: 2290



Сообщение #12 Korchy » 20.09.2016, 10:36

А может кто понятно объяснить, что такое layout ?
В случае
Код: Выделить всё
def sampleFunction(self, context):
    self.layout.operator("operator_id", icon="xxx")
что происходит?
Korchy M
Аватара
Сообщения: 2290



  • 1

Сообщение #13 andreymal » 20.09.2016, 10:46

Какая-то переменная в объекте, который лежит в переменной self :)
Читая эту подпись, вы впустую потратили 5 секунд своей жизни.
andreymal M
Аватара
Сообщения: 1075

Сообщение #14 Korchy » 20.09.2016, 10:57

Подозреваю, что это какая-то стандартная переменная api т.к. встречает постоянно в скриптах-аддонах. Только не доходит до меня что именно она делает.
Korchy M
Аватара
Сообщения: 2290



  • 1

Сообщение #15 andreymal » 20.09.2016, 10:59

Без инфы, где это всё расположено и кем вызвыается, это может быть чем угодно
Читая эту подпись, вы впустую потратили 5 секунд своей жизни.
andreymal M
Аватара
Сообщения: 1075

Сообщение #16 Korchy » 20.09.2016, 11:02

Ну вот например добавление вызова класса-оператора в меню Add mesh

Код: Выделить всё
def add_to_menu(self, context) :
    self.layout.operator("mesh.make_tetrahedron", icon = "PLUGIN")
#end add_to_menu

def register() :
    bpy.utils.register_class(MakeTetrahedron)
    bpy.types.INFO_MT_mesh_add.append(add_to_menu)
#end register
Korchy M
Аватара
Сообщения: 2290



Сообщение #17 andreymal » 20.09.2016, 11:13

Korchy писал(а):bpy.types.INFO_MT_mesh_add
А такого в документации нету
Читая эту подпись, вы впустую потратили 5 секунд своей жизни.
andreymal M
Аватара
Сообщения: 1075

Сообщение #18 Korchy » 20.09.2016, 11:15

Если бы все было так просто, я бы не задавал вопроса ) В документации я пытался шарить. Однако это работает.
Korchy M
Аватара
Сообщения: 2290



  • 1

Сообщение #19 andreymal » 20.09.2016, 11:32

Ну без документации формально всё ещё можно сказать, что тут может происходить вообще что угодно :)

А по исходникам блендера INFO_MT_mesh_add это объект класса Menu, а у этого Menu бывает layout, а там уже кажется про это в документации есть :)

Причём там такой комментарий стоит:
Код: Выделить всё
# XXX: INFO_MT_ names used to keep backwards compatibility (Addons etc that hook into the menu)
Читая эту подпись, вы впустую потратили 5 секунд своей жизни.
andreymal M
Аватара
Сообщения: 1075

Сообщение #20 Korchy » 20.09.2016, 11:41

Тоже это находил, но не придал значения комментарию. Т.е. получается такой способ добавления пунктов меня устаревший?
Насколько я вообще понимаю, layout это какая-то структура, в которой расписаны пункты этого самого меню. Но все равно не могу добраться до его подробного описания (.

Добавлено спустя 8 минут 4 секунды:
Хм, хотя в документации на 2.77 используется все равно этот же способ
https://www.blender.org/api/blender_python_api_2_77a_release/bpy.types.Menu.html

Вроде нашел описание структуры layout
https://www.blender.org/api/blender_python_api_2_ ... Layout.html#bpy.types.UILayout
но все равно ничего не понял (
Korchy M
Аватара
Сообщения: 2290



След.

Вернуться в Плагины

Кто сейчас на форуме (по активности за 5 минут)

Сейчас этот раздел просматривают: 1 гость