понедельник, 10 октября 2016 г.

Код оператора будущего аддона.

    Разобрался с выбором объекта и с прочими появившимися проблемами. Что еще надо сделать:
a) Добавить модификатор Solidify, и соответственно применение его.
b) Оформить некоторые переменные как Property
c) Написать первую версию Гуя, и разместить его в DATA

    Выпотрошил пример Simple Operator из примеров блендера и заменил функционал. Замучился я с применением модификатора взрыва, никак не хотел он нормально применяться, пришлось каждый раз пересчитывать его данные, как итог, результат не похож на настроенный оригинал. Все остальное позже доделаю, а пока можно почитать, да и потестить ( с подсветкой синтаксиса и комментариями!):



import bpy

                                    
def main(context):
    """
    да, я знаю, что есть такая штука, как многострочные комментарии, но мне не
    нравится их цвет
    """

    print('<<<<<>>>>>') #debug
    # объект, который надо взорвать, он же изначальный, он же породитель
    object = bpy.context.object
    # имя этого объекта
    name = object.name
    # список имен будущих клонов объекта
    listName = []
    # эта переменная нужна для записи индекса клона в списке имен
    index = 0
    #смещение, плюс/минус сколько фреймов будет занимать ключ формы клона
    #оно же через сколько кадров будет создаваться клон 
    diff = 5
    # кадры анимации, и так понятно ху из ху
    start_anim = 1
    end_anim = 26
    
    # Здесь мы будем создавать клоны изначального объекта
    
    for frame in range(start_anim, end_anim, diff):
        # выбираем и делаем активным объект, который надо взорвать
        object.select = True
        bpy.context.scene.objects.active = object
#        print(context.object.name) #debug
        # делаем его клон 
        bpy.ops.object.duplicate()

        #Вот теперь есть нюанс, после применения оператора duplicate(), активным 
        #и выбранным станет свежесозданный клон, c которыv мы и будем работать. 
        #Если бы нам надо было работать с изначальным объектом, то пришлось бы 
        #повторять его выбор и активизацию

        # собственно объект-клон
        newOb = bpy.context.scene.objects.active
        # переименовываем клон, его имя потом будет использоваться как имя
        # ключа формы
        newOb.name = name + 'Explode' + str(frame)
        # добавляем в список имен КОРТЕЖ, содержащий имя клона, кадр анимации,
        # и индекс кортежа в списке
        listName.append((newOb.name, frame, index))
        # изменяем переменную, что бы не оказалось, что у разных кортежей разный
        # индекс
        index = index + 1
#        print(context.object.name) #debug
        # снимаем выделение со всех объектов
        bpy.ops.object.select_all(action = 'DESELECT')
#        print(newOb.data.name) #debug
        
#    print('____') #debug
    
    # Здесь мы будем применять (Apply) модификатор взрыва и удалять клонам 
    # систему частиц
        
    for name, frame, index in listName:
        # выковыриваем по имени нужный нам клон
        obj = bpy.context.scene.objects[name]
        #выбираем его и делаем его активным
        obj.select = True
        bpy.context.scene.objects.active = obj
        # выставляем текущий кадр сцены по упакованному в список имен
        bpy.context.scene.frame_current = frame
        # обновляем данные модификатор взрыва, к сожалению, без этого никак
        # нельзя обойтись, как следствие, результат будет отличаться от 
        # настроенного на изначальном объекте. 
        bpy.ops.object.explode_refresh(modifier = 'Explode')
#        print(frame, obj.name, bpy.context.selected_objects, context.object.name, 
#       bpy.context.scene.frame_current) #debug
        # применяем модификатор взрыва
        status = bpy.ops.object.modifier_apply(modifier = 'Explode')
#        print(status) #debug
        # удаляем систему частиц на клоне
        bpy.ops.object.particle_system_remove()
        # снимем выделение на клоне
        bpy.ops.object.select_all(action = 'DESELECT')
                
#        print('____________') #debug
        
#    print(listName) #debug
    
    # Здесь будем добавлять клонов как ключи формы, причем самому первому клону,
    # потому что нельзя добавит объект в ключи другому объекту, если у них 
    # разное число вершин.
    
    for name, frame, index in listName:
        # пропускаем первого клона, на него будем писать ключи формы
        if index == 0:
            continue
        else
            # понятно, выковыриваем клон(не первый) по имени, он пойдет в ключ формы
            currObj = bpy.context.scene.objects[name]
            # выбираем его
            currObj.select = True 
            # получаем первого клона
            explObject = bpy.context.scene.objects[listName[0][0]]
            # выбираем его и делаем его активным
            explObject.select = True
            bpy.context.scene.objects.active = explObject
            # пишем текущий клон в ключ формы первого клона
            bpy.ops.object.join_shapes()
            # снимем выделение со всех объектов сцены
            bpy.ops.object.select_all(action = 'DESELECT')
            # снова выбираем текущего клона и в этот раз делаем его активным
            bpy.context.scene.objects.active = currObj
            currObj.select = True 
            # удаляем текущий клон       
            bpy.ops.object.delete()
            
    # Здесь будем анимировать ключи формы 
           
    # снимаем выделение со всех объектов, на всякий пожарный    
    bpy.ops.object.select_all(action = 'DESELECT')
    # выделям первый и теперь уже единственный клон
    objExpl = bpy.context.scene.objects[listName[0][0]]
    bpy.context.scene.objects.active = objExpl
    objExpl.select = True
    # получаем его список ключей форм
    shapeKeys = objExpl.data.shape_keys

    for name, frame, index in listName:
        # достаем ключ формы по имени, на всякий случай проверяя, есть ли такой
        if name in shapeKeys.key_blocks:
            # текущий ключ формы
            currBlock = shapeKeys.key_blocks[name]
            # генерируем список из кортежей "значение - кадр"
            frameList = [(0.0, frame-diff), (1.0, frame), (0.0, frame+diff)]
            # И по этому списку задаем ключи анимации ключам формы
            for J in frameList:
#                print(J) #debug
                currBlock.value = J[0]
                currBlock.keyframe_insert("value", frame = J[1])
#            print(currBlock.name) #debug


        

class explodeToShape(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.explode_to_shape"
    bl_label = "Explode To Shape"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        main(context)
        return {'FINISHED'}


def register():
    bpy.utils.register_class(explodeToShape)


def unregister():
    bpy.utils.unregister_class(explodeToShape)


if __name__ == "__main__":
    register()

    # test call

    bpy.ops.object.explode_to_shape()


Комментариев нет:

Отправить комментарий