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

import bpy
import math
import util
import pyutil

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['plano'] if 'plano' 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
# exemplos:
# 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
# @param obj: (objeto) bone, mesh, e.g.
# @param current_frame: (int) posicao onde o primeiro keyframe vai ser inserido
# @param raio: (int) raio da circunferencia
# @param periodo: (int) quantidade de keyframes necessarios para completar uma volta completa
# @param x: (int) in [0,1,2] define qual eixo vai variar no seno (0 = eixo X, 1 = eixo Y, 2 = eixo Z)
# @param y: (int) in [0,1,2] define qual eixo vai variar no cosseno (0 = eixo X, 1 = eixo Y, 2 = eixo Z)
# @param usar_lado_oposto: (bool) inverte o lado da primeira posicao (pode ser util em alguns casos para espelhar)
# @param usar_sentido_oposto (bool) inverte o sentido do movimento (horario para anti-horario)
def circular(obj, current_frame, raio, periodo, x = 0, y = 1, usar_lado_oposto = False, usar_sentido_oposto = False, meia_volta = False):
    # limita inferiormente
    if (periodo < 16):
        periodo = 16
    # limita superiormente
    elif (periodo > 360):
        periodo = 360
    # muda lado inicial
    if (usar_lado_oposto):
        k = round(periodo / 2)
    else:
        k = 0
    # evita estouro dos indices
    x %= 3
    y %= 3
    # inverte direcao do movimento
    if (usar_sentido_oposto):
        tmp = x
        x = y
        y = tmp
    # copia posicao inicial para transladar
    loc = [obj.location[0], obj.location[1], obj.location[2]]
    # semi-circular
    limite = periodo + k
    if (meia_volta):
        limite = round(limite / 2)
    for i in range(k, limite + 1):
        # reduz a quantidade de keyframes
        if (current_frame % 2 == 0):
            obj.location[x] = loc[x] + (raio * math.cos(i / periodo * (2 * math.pi)))
            obj.location[y] = loc[y] + (raio * math.sin(i / periodo * (2 * math.pi)))
            util.keyframe_insert(obj, 'location', current_frame)
        current_frame += 1
    util.keyframe_insert(obj, 'location', current_frame)
    return periodo - 1

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'], js_movement['articulacao_inicial'], js_movement['orientacao']]
    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'], js_movement['articulacao_final'], js_movement['orientacao']]
    util.setPose(hand_actions, hand_param, [current_frame], bones)
    util.keyframe_insert(bones, 'location', current_frame)
    return current_frame