facial.py 5.36 KB
# -*- coding: UTF-8 -*-

import bpy
import util

# duracao na posicao selecionada
dict_duration = {
    'lento': 15,
    'normal': 10,
    'rapido': 5
}

# tempo de entrada e saida na posicao selecionada
dict_transition = {
    'lento': 15,
    'normal': 10,
    'rapido': 5
}

# insere keyframes aos bones selecionados anteriormente e passados como parametro
def keyframe_insert(current_frame = 0, pose_bones = bpy.context.object.pose.bones, keyframe_types = ['location', 'rotation_quaternion']):
    # verifica se existe apenas um bone
    if (isinstance(pose_bones, int) or isinstance(pose_bones, str)):
        # verifica se existe apenas um tipo de insercao de keyframe
        if (isinstance(keyframe_types, str)):
            bpy.context.object.pose.bones[pose_bones].keyframe_insert(index = -1, frame = current_frame, group = bpy.context.object.pose.bones[pose_bones].name, data_path = keyframe_types)
        # verifica se existe mais de um tipo de insercao de keyframe
        elif (isinstance(keyframe_types, list)):
            for keyframe_type in keyframe_types:
                bpy.context.object.pose.bones[bones].keyframe_insert(index = -1, frame = current_frame, group = bpy.context.object.pose.bones[pose_bones].name, data_path = keyframe_type)
    # verifica se existe mais de um bone
    elif (isinstance(pose_bones, list)):
        for bone in pose_bones:
            # verifica se existe apenas um tipo de insercao de keyframe
            if (isinstance(keyframe_types, str)):
                bpy.context.object.pose.bones[bone].keyframe_insert(index = -1, frame = current_frame, group = bpy.context.object.pose.bones[bone].name, data_path = keyframe_types)
            # verifica se existe mais de um tipo de insercao de keyframe
            elif (isinstance(keyframe_types, list)):
                for keyframe_type in keyframe_types:
                    bpy.context.object.pose.bones[bone].keyframe_insert(index = -1, frame = current_frame, group = bpy.context.object.pose.bones[bone].name, data_path = keyframe_type)
    return

# aplica biblioteca(s) de pose(s) e seu respectivo indice
def apply_pose(index = 0, pose_library = list(bpy.data.actions)):
    # verifica se deve aplicar apenas uma biblioteca
    if (isinstance(pose_library, int) or isinstance(pose_library, str)):
        # verifica biblioteca fake_user
        if (bpy.data.actions[pose_library].use_fake_user):
            bpy.context.object.pose_library = bpy.data.actions[pose_library]
            bpy.ops.poselib.apply_pose(pose_index = index)
    # verifica se deve aplicar mais de uma biblioteca
    elif (isinstance(pose_library, list)):
        for library in pose_library:
            # verifica biblioteca fake_user
            if (library.use_fake_user):
                bpy.context.object.pose_library = library
                bpy.ops.poselib.apply_pose(pose_index = index)
    bpy.context.object.pose_library = None
    return

# consolida o movimento (faz insercao dos keyframes) e incrementa a timeline
def set_expression(timeline_facial, index, frame_duration = dict_duration['normal'], frame_transition = 0):
    library_name = util.facial_expression_id
    bones_facial = util.dict_bones[library_name]
    util.select_bones(bones_facial)
    # TODO separar bones 'location' e 'rotation_quaternion'
    keyframe_insert(timeline_facial, bones_facial, ['location', 'rotation_quaternion'])
    apply_pose(index, library_name)
    timeline_facial += frame_transition
    keyframe_insert(timeline_facial, bones_facial, ['location', 'rotation_quaternion'])
    timeline_facial += frame_duration
    keyframe_insert(timeline_facial, bones_facial, ['location', 'rotation_quaternion'])
    timeline_facial += frame_transition
    util.deselect_bones(bones_facial)
    return timeline_facial

# decodifica objeto JSON
def decode_expression(timeline_facial, js_facial, initial_interpolation = dict_duration['normal']):
    global dict_duration
    global dict_transition
    index = js_facial['expressao']
    frame_duration = dict_duration[js_facial['duracao']]
    frame_transition = dict_duration[js_facial['transicao']]
    # insere o primeiro keyframe
    if (timeline_facial == 0):
        set_expression(timeline_facial, 0, initial_interpolation)
    set_expression(timeline_facial, index, frame_duration, frame_transition)
    set_expression(timeline_facial, 0, frame_duration)
    return timeline_facial

"""
# unit test
def main():
    import random
    interpolation_start = 20
    interpolation_end = 20
    pose_max_range = round(bpy.data.actions[library_name].frame_range[1])

    util.delete_all_keyframes()
    apply_pose(0, library_name)

    js_facial = {"expressao": random.randint(0, pose_max_range), "transicao": 'normal', "duracao": 'normal'}
    print('facial expression %d current frame:' % (js_facial['expressao']), decode_expression(js_facial))

    js_facial = {"expressao": random.randint(0, pose_max_range), "transicao": 'normal', "duracao": 'normal'}
    print('facial expression %d current frame:' % (js_facial['expressao']), decode_expression(js_facial))

    #for i in range(0, pose_max_range + 1):
    #    js_facial = {"expressao": i, "transicao": 'normal', "duracao": 'normal'}
    #    print('facial expression %d current frame:' % (js_facial['expressao']), decode_expression(js_facial))

    bpy.context.scene.frame_end = timeline_facial + interpolation_end
    bpy.ops.screen.animation_play(reverse = False)

if __name__ == "__main__":
    main()
"""