moves.py 18.1 KB
# -*- coding: UTF-8 -*-

import bpy
import math
import util
import pyutil

def facial_insert_keyframe(current_frame):
    bones_facial = util.dict_bones[util.facial_expression_id]
    util.select_bones(bones_facial)
    for bone in bones_facial:
        for keyframe_type in ["location", "rotation_quaternion"]:
            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)
    util.deselect_bones(bones_facial)

def facial_set_expression(timeline_facial, index, frame_duration, frame_transition):
    facial_insert_keyframe(timeline_facial)
    util.deselect_bones()
    bpy.context.object.pose_library = bpy.data.actions[util.facial_expression_id]
    bpy.ops.poselib.apply_pose(pose_index = index)
    bpy.context.object.pose_library = None
    timeline_facial += frame_transition
    facial_insert_keyframe(timeline_facial)
    timeline_facial += frame_duration
    facial_insert_keyframe(timeline_facial)
    timeline_facial += frame_transition
    return timeline_facial

def facial(js_facial, current_frame, frame_jump):
    dict_duration = {
        "inicial": 5,
        "lento": 15,
        "normal": 10,
        "rapido": 5,
        "final": 5,
    }
    dict_transition = {
        "inicial": 0,
        "lento": 15,
        "normal": 10,
        "rapido": 5,
        "final": 0
    }
    index = js_facial["expressao"]
    frame_duration = dict_duration[js_facial["duracao"]]
    frame_transition = dict_transition[js_facial["transicao"]]
    if (current_frame == 0):
        current_frame = facial_set_expression(current_frame, 0, initial_interpolation, dict_transition["normal"])
    current_frame = facial_set_expression(current_frame, index, frame_duration, frame_transition)
    current_frame = facial_set_expression(current_frame, 0, frame_duration, dict_transition["normal"])
    return current_frame

def read_hand_param(mov_param):
    conf_param = mov_param['configuracao'] if 'configuracao' in mov_param else 0
    artic_param = mov_param['articulacao'] if 'articulacao' in mov_param else 0
    orient_param = mov_param['orientacao'] if 'orientacao' in mov_param else 0
    return [conf_param, artic_param, orient_param]

def contato(action, contact_type, mov_param, bones, is_right_hand, initialFrame = 18, frameJump = 10):
    if (contact_type == "alisar"):
        currentFrame = alisar(action, mov_param, bones, is_right_hand, initialFrame, frameJump)
    elif (contact_type == "cocar"):
        currentFrame = cocar(action, mov_param, bones, initialFrame,  frameJump)
    elif (contact_type == "tocar"):
        currentFrame = tocar(action, mov_param, bones, is_right_hand, initialFrame, frameJump)
    elif (contact_type == "riscar"):
        currentFrame = riscar(action, mov_param, bones, is_right_hand, initialFrame, frameJump)
    return currentFrame

def riscar(action, mov_param, bones, is_right_hand, initialFrame = 25, frameJump = 10, bnAntBracoDegree = 2, bnMaoDegree = 45):
    currentFrame = initialFrame
    handParam = read_hand_param(mov_param)
    lado = "R" if is_right_hand else "L"
    bnAntBraco = bpy.context.object.pose.bones["BnAntBraco." + lado]
    currentFrame += frameJump
    util.apply_rotation(bnAntBraco, "Z", currentFrame, bnAntBracoDegree)
    currentFrame += frameJump
    util.apply_rotation(bnAntBraco, "Z", currentFrame, (-1)*(bnAntBracoDegree+1))
    currentFrame = initialFrame
    util.setPose(action, handParam, [currentFrame], bones)
    bnMao = bpy.context.object.pose.bones["BnMao." + lado]
    currentFrame += frameJump
    util.apply_rotation(bnMao, "Y", currentFrame, bnMaoDegree)
    currentFrame += int(frameJump/2)
    util.apply_rotation(bnMao, "Y", currentFrame, (-1)*bnMaoDegree)
    currentFrame += int(frameJump/2)
    util.apply_rotation(bnMao, "Y", currentFrame, (-2)*bnMaoDegree)
    currentFrame += frameJump
    util.setPose(action, handParam, [currentFrame], bones)
    return currentFrame

def tocar(action, mov_param, bones, is_right_hand, initialFrame = 25, degree = 30, frameJump = 10):
    currentFrame = initialFrame
    handParam = read_hand_param(mov_param)
    util.setPose(action, handParam, [initialFrame], bones)
    pose = util.armature.pose.bones["ik_FK.R" if is_right_hand else "ik_FK.L"]
    lado = "BnMao.R" if is_right_hand else "BnMao.L"
    bnMao =  bpy.context.object.pose.bones[lado]
    currentFrame += frameJump
    util.apply_rotation(bnMao, "X", currentFrame, -degree)
    pose = util.armature.pose.bones["ik_FK.R" if is_right_hand else "ik_FK.L"]
    currentFrame += frameJump
    util.apply_rotation(bnMao, "X", currentFrame, degree)
    util.setPose(action[0:2], handParam[0:2], [currentFrame], bones)
    return currentFrame

def cocar(action, mov_param, bones, initialFrame = 18, frameJump = 10):
    currentFrame = initialFrame
    pa_index = mov_param['articulacao'] if 'articulacao' in mov_param else 0
    repetition = mov_param['repeticoes'] if 'repeticoes' in mov_param else 2
    for i in range(0, repetition):
        util.setPose(action, [util.cocar_mao_aberta_index, pa_index, util.cocar_orientation_index], [currentFrame], bones, False)
        currentFrame += frameJump
        util.setPose(action, [util.cocar_mao_fechada_index, pa_index, util.cocar_orientation_index], [currentFrame], bones, False)
        currentFrame += frameJump
    return currentFrame

def alisar(action, mov_param, bones, is_right_hand, initialFrame = 18, frameJump = 10, width = 0.25):
    currentFrame = initialFrame
    plane = mov_param['orientacao_movimento'] if 'orientacao_movimento' in mov_param else "perpendicular"
    repetition = mov_param['repeticoes'] if 'repeticoes' in mov_param else 2
    handParam = read_hand_param(mov_param)
    util.setPose(action, handParam, [currentFrame], bones)
    boneIK = util.armature.pose.bones["ik_FK.R" if is_right_hand else "ik_FK.L"]
    if (plane == "perpendicular"):
        currentFrame = alisar_xy(boneIK, 1, repetition, currentFrame, frameJump, width)
    elif (plane == "paralelo"):
        currentFrame = alisar_xy(boneIK, 0, repetition, currentFrame, frameJump, width)
    elif (plane == "diagonal-direita"):
        currentFrame = alisar_diagonal(boneIK, True, repetition, currentFrame, frameJump, width)
    elif (plane == "diagonal-esquerda"):
        currentFrame = alisar_diagonal(boneIK, False, repetition, currentFrame, frameJump, width)
    util.setPose(action, handParam, [currentFrame], bones)
    return currentFrame

def alisar_xy(boneIK, orientation_index, repetition, initialFrame = 18, frameJump = 10, width = 0.25):
    currentFrame = initialFrame
    location = util.get_bone_data_from_frame(boneIK, currentFrame, 'location')
    center = location.x, location.y, location.z
    for i in range(0, repetition):
        boneIK.location = center
        boneIK.location[orientation_index] = center[orientation_index] - width
        util.keyframe_insert(boneIK, 'location', currentFrame)
        currentFrame += frameJump
        boneIK.location = center
        boneIK.location[orientation_index] = center[orientation_index] + width
        util.keyframe_insert(boneIK, 'location', currentFrame)
        currentFrame += frameJump
    return currentFrame

def alisar_diagonal(boneIK, to_right, repetition, initialFrame = 18, frameJump = 10, width = 0.25):
    currentFrame = initialFrame
    location = util.get_bone_data_from_frame(boneIK, currentFrame, 'location')
    center =  location.x, location.y, location.z
    for i in range(0, repetition):
        boneIK.location = center
        boneIK.location[0] = center[0] - width if to_right else center[0] - width
        boneIK.location[1] = center[1] - width if to_right else center[1] + width
        util.keyframe_insert(boneIK, 'location', currentFrame)
        currentFrame += frameJump
        boneIK.location = center
        boneIK.location[0] = center[0] + width if to_right else center[0] + width
        boneIK.location[1] = center[1] + width if to_right else center[1] - width
        util.keyframe_insert(boneIK, 'location', currentFrame)
        currentFrame += frameJump
    return currentFrame

# Obs.: A velocidade do movimento vai ser a relacao entre tamanho do raio e o periodo
#       quanto maior o periodo mais keyframes
#       quanto menor o raio mais rapido

# circular:
# raio: "pequeno" raio = 0.5, velocidade: "rapido" periodo = 25
# raio: "pequeno" raio = 0.5, velocidade: "normal" periodo = 35
# raio: "pequeno" raio = 0.5, velocidade: "lento" periodo = 45
# raio: "normal" raio = 1.0, velocidade: "rapido" periodo = 35
# raio: "normal" raio = 1.0, velocidade: "normal" periodo = 45
# raio: "normal" raio = 1.0, velocidade: "lento" periodo = 55
# raio: "grande" raio = 1.5, velocidade: "rapido" periodo = 45
# raio: "grande" raio = 1.5, velocidade: "normal" periodo = 55
# raio: "grande" raio = 1.5, velocidade: "lento" periodo = 65
def circular(js_movement, current_frame, frame_jump, is_right_hand, is_semicircular = False):
    dict_ray = {
        "pequeno": 0.5,
        "normal": 1.0,
        "grande": 1.5
    }
    dict_period = {
        "lento": 55,
        "normal": 45,
        "rapido": 35
    }
    dict_calc = {
        "pequeno": -10,
        "normal": 0,
        "grande": 10
    }
    dict_axis = {
        "frente-esquerda": [2, 0, 1],
        "frente-cima": [2, 1, 0],
        "esquerda-cima": [0, 1, 2]
    }
    actions = util.right_hand_actions if (is_right_hand) else util.left_hand_actions
    bones = util.right_bones_conf if (is_right_hand) else util.left_bones_conf
    hand_param = read_hand_param(js_movement)
    ik = bpy.context.object.pose.bones["ik_FK.R" if (is_right_hand) else "ik_FK.L"]
    opposite_side = js_movement["lado_oposto"]
    period = dict_period[js_movement["velocidade"]] + dict_calc[js_movement["raio"]]
    ray = dict_ray[js_movement["raio"]]
    reverse_way = js_movement["sentido_inverso"]
    x = dict_axis[js_movement["plano"]][0]
    y = dict_axis[js_movement["plano"]][1]
    #z = dict_axis[js_movement["plano"]][2]
    k = round(period / 2) if (opposite_side) else 0
    if (reverse_way):
        tmp = x
        x = y
        y = tmp
    util.setPose(actions, hand_param, [current_frame], bones, False)
    util.keyframe_insert(bones, "location", current_frame, False, False)
    ik_loc = [ik.location[0], ik.location[1], ik.location[2]]
    limit = round(period / 2) + k if (is_semicircular) else period + k
    for i in range(k, limit + 1):
        bpy.context.object.pose_library = bpy.data.actions[util.conf_direita_id if (is_right_hand) else util.conf_esquerda_id]
        bpy.ops.poselib.apply_pose(pose_index = hand_param[0])
        bpy.context.object.pose_library = None
        util.keyframe_insert(bones, "location", current_frame, False)
        util.keyframe_insert(bones, "rotation_quaternion", current_frame, False)
        ik.location[x] = ik_loc[x] + (ray * math.cos(i / period * (2 * math.pi)))
        ik.location[y] = ik_loc[y] + (ray * math.sin(i / period * (2 * math.pi)))
        util.keyframe_insert(ik, "location", current_frame, False)
        util.keyframe_insert(ik, "rotation_quaternion", current_frame, False)
        current_frame += 1
    return current_frame + frame_jump

# 'lado_oposto'     true inverte o sentido do vetor direcional
# 'sentido_inverso' true inverte o sentido do plano

# helicoidal
# raio: "pequeno" raio = 0.2, velocidade: "rapido" periodo = 25
# raio: "pequeno" raio = 0.2, velocidade: "normal" periodo = 35
# raio: "pequeno" raio = 0.2, velocidade: "lento" periodo = 45
# raio: "normal" raio = 0.6, velocidade: "rapido" periodo = 35
# raio: "normal" raio = 0.6, velocidade: "normal" periodo = 45
# raio: "normal" raio = 0.6, velocidade: "lento" periodo = 55
# raio: "grande" raio = 0.8, velocidade: "rapido" periodo = 45
# raio: "grande" raio = 0.8, velocidade: "normal" periodo = 55
# raio: "grande" raio = 0.8, velocidade: "lento" periodo = 65
def helicoidal(js_movement, current_frame, frame_jump, is_right_hand):
    dict_ray = {
        "pequeno": 0.2,
        "normal": 0.6,
        "grande": 0.8
    }
    dict_period = {
        "lento": 55,
        "normal": 45,
        "rapido": 35
    }
    dict_calc = {
        "pequeno": -10,
        "normal": 0,
        "grande": 10
    }
    dict_axis = {
        "frente-esquerda": [2, 0, 1],
        "frente-cima": [2, 1, 0],
        "esquerda-cima": [0, 1, 2]
    }
    actions = util.right_hand_actions if (is_right_hand) else util.left_hand_actions
    bones = util.right_bones_conf if (is_right_hand) else util.left_bones_conf
    hand_param = read_hand_param(js_movement)
    ik = bpy.context.object.pose.bones["ik_FK.R" if (is_right_hand) else "ik_FK.L"]
    opposite_side = js_movement["lado_oposto"]
    period = dict_period[js_movement["velocidade"]] + dict_calc[js_movement["raio"]]
    ray = dict_ray[js_movement["raio"]]
    reverse_way = js_movement["sentido_inverso"]
    # print('raio: "%s" raio = %.1f, velocidade: "%s" periodo = %d' % (js_movement["raio"], ray, js_movement["velocidade"], period))
    x = dict_axis[js_movement["plano"]][0]
    y = dict_axis[js_movement["plano"]][1]
    z = dict_axis[js_movement["plano"]][2]
    # print("x = %.1f y = %.1f z = %.1f" % (x, y, z))
    k = 0
    if (reverse_way):
        tmp = x
        x = y
        y = tmp
    util.setPose(actions, hand_param, [current_frame], bones, False)
    util.keyframe_insert(bones, "location", current_frame, False, False)
    ik_loc = [ik.location[0], ik.location[1], ik.location[2]]
    limit = period + k
    for i in range(k, 2 * (limit + 1)):
        bpy.context.object.pose_library = bpy.data.actions[util.conf_direita_id if (is_right_hand) else util.conf_esquerda_id]
        bpy.ops.poselib.apply_pose(pose_index = hand_param[0])
        bpy.context.object.pose_library = None
        util.keyframe_insert(bones, "location", current_frame, False)
        util.keyframe_insert(bones, "rotation_quaternion", current_frame, False)
        ik.location[x] = ik_loc[x] + (ray * math.cos(i / period * (2 * math.pi)))
        ik.location[y] = ik_loc[y] + (ray * math.sin(i / period * (2 * math.pi)))
        distance_inc = (i / period) - ray
        if (opposite_side):
            distance_inc = -distance_inc
        ik.location[z] = ik_loc[z] + distance_inc
        util.keyframe_insert(ik, "location", current_frame, False)
        util.keyframe_insert(ik, "rotation_quaternion", current_frame, False)
        current_frame += 1
    return current_frame + frame_jump

def pontual(js_movement, current_frame, frame_jump, is_right_hand):
    hand_param = read_hand_param(js_movement)
    bones = util.right_bones_conf if is_right_hand else util.left_bones_conf
    hand_actions = util.right_hand_actions if is_right_hand else util.left_hand_actions
    util.keyframe_insert(bones, "location", current_frame)
    current_frame += frame_jump
    util.setPose(hand_actions, hand_param, [current_frame], bones)
    current_frame += frame_jump
    util.keyframe_insert(bones, "location", current_frame)
    return current_frame

def retilineo(js_movement, current_frame, frame_jump, is_right_hand):
    hand_param = [js_movement["configuracao_inicial"], js_movement["articulacao_inicial"], js_movement["orientacao_inicial"]]
    bones = util.right_bones_conf if is_right_hand else util.left_bones_conf
    hand_actions = util.right_hand_actions if is_right_hand else util.left_hand_actions
    util.keyframe_insert(bones, "location", current_frame)
    current_frame += frame_jump
    util.setPose(hand_actions, hand_param, [current_frame], bones)
    current_frame += 2 * frame_jump
    hand_param = [js_movement["configuracao_final"], js_movement["articulacao_final"], js_movement["orientacao_final"]]
    util.setPose(hand_actions, hand_param, [current_frame], bones)
    util.keyframe_insert(bones, "location", current_frame)
    return current_frame

def semicircular(js_movement, current_frame, frame_jump, is_right_hand):
    return circular(js_movement, current_frame, frame_jump, is_right_hand, True)

def senoidal(js_movement, current_frame, frame_jump, is_right_hand):
    dict_wave = {
        "pequeno": 0.1,
        "normal": 0.2,
        "grande": 0.3
    }
    dict_distance_inc = {
        "pequeno": 0.005,
        "normal": 0.010,
        "grande": 0.015
    }
    dict_speed = {
        "rapido": 2,
        "normal": 3,
        "lento": 4
    }
    dict_axis = {
        "esquerda": {
            "frente-tras": [0, 2, 1],
            "cima-baixo": [0, 1, 2]
        },
        "cima": {
            "frente-tras": [1, 2, 0],
            "esquerda-direita": [1, 0, 2]
        },
        "frente": {
            "esquerda-direita": [2, 0, 1],
            "cima-baixo": [2, 1, 0]
        }
    }
    axis_dir = dict_axis[js_movement["direcao"]][js_movement["plano_deslocamento"]][0]
    axis_sin = dict_axis[js_movement["direcao"]][js_movement["plano_deslocamento"]][1]
    reverse_way = js_movement["direcao_oposta"]
    distance_inc = dict_distance_inc[js_movement["distancia"]]
    # TODO adaptar velocidade
    # speed = dict_speed[js_movement["velocidade"]]
    wave_len = dict_wave[js_movement["tamanho_onda"]]
    actions = util.right_hand_actions if (is_right_hand) else util.left_hand_actions
    bones = util.right_bones_conf if (is_right_hand) else util.left_bones_conf
    hand_param = read_hand_param(js_movement)
    ik = bpy.context.object.pose.bones["ik_FK.R" if (is_right_hand) else "ik_FK.L"]
    util.setPose(actions, hand_param, [current_frame], bones, False)
    util.keyframe_insert(bones, "location", current_frame, False, False)
    ik_loc = [ik.location[0], ik.location[1], ik.location[2]]
    pose_library = bpy.data.actions[util.conf_direita_id if (is_right_hand) else util.conf_esquerda_id]
    for i in range(0, 100):
        bpy.context.object.pose_library = pose_library
        bpy.ops.poselib.apply_pose(pose_index = hand_param[0])
        bpy.context.object.pose_library = None
        util.keyframe_insert(bones, "location", current_frame, False)
        util.keyframe_insert(bones, "rotation_quaternion", current_frame, False)
        ik.location[axis_dir] += -distance_inc if (reverse_way) else distance_inc
        ik.location[axis_sin] = ik_loc[axis_sin] + math.sin(i * wave_len)
        util.keyframe_insert(ik, "location", current_frame, False)
        util.keyframe_insert(ik, "rotation_quaternion", current_frame, False)
        current_frame += 1
    return current_frame + frame_jump