# -*- 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): currentFrame = initialFrame 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[x, y, z, opposite_side, reverse_way] dict_axis = { "baixo-direita" : [1, 0, 2, True, False], # a "baixo-esquerda" : [1, 0, 2, True, True], # h "baixo-frente" : [1, 2, 0, True, True], # a "baixo-tras" : [1, 2, 0, True, False], # h "cima-direita" : [1, 0, 2, False, True], # h "cima-esquerda" : [1, 0, 2, False, False], # a "cima-frente" : [1, 2, 0, False, False], # h "cima-tras" : [1, 2, 0, False, True], # a "direita-baixo" : [0, 1, 2, True, False], # h "direita-cima" : [0, 1, 2, True, True], # a "direita-frente" : [0, 2, 1, True, True], # a "direita-tras" : [0, 2, 1, True, False], # h "esquerda-baixo" : [0, 1, 2, False, True], # a "esquerda-cima" : [0, 1, 2, False, False], # h "esquerda-frente": [0, 2, 1, False, False], # h "esquerda-tras" : [0, 2, 1, False, True], # a "frente-baixo" : [2, 1, 0, False, True], # h "frente-cima" : [2, 1, 0, False, False], # a "frente-direita" : [2, 0, 1, False, True], # h "frente-esquerda": [2, 0, 1, False, False], # h "tras-baixo" : [2, 1, 0, True, False], # a "tras-cima" : [2, 1, 0, True, True], # h "tras-direita" : [2, 0, 1, True, False], # h "tras-esquerda" : [2, 0, 1, True, True] # h } if (is_semicircular): dict_axis["baixo-esquerda"] = [1, 0, 2, False, True] dict_axis["baixo-frente"] = [1, 2, 0, False, True] dict_axis["cima-direita"] = [1, 0, 2, True, True] dict_axis["cima-tras"] = [1, 2, 0, True, True] dict_axis["direita-cima"] = [0, 1, 2, False, True] dict_axis["direita-frente"] = [0, 2, 1, False, True] dict_axis["esquerda-baixo"] = [0, 1, 2, True, True] dict_axis["esquerda-tras"] = [0, 2, 1, True, True] dict_axis["frente-baixo"] = [2, 1, 0, True, True] dict_axis["frente-direita"] = [2, 0, 1, True, True] dict_axis["tras-cima"] = [2, 1, 0, False, True] dict_axis["tras-esquerda"] = [2, 0, 1, False, True] plan = js_movement["plano"] if ("sentido_inverso" in js_movement.keys()): reverse_way = js_movement["sentido_inverso"] if (reverse_way): if ("-baixo" in plan): plan = plan.replace("-baixo", "-cima", 1) elif("-cima" in plan): plan = plan.replace("-cima", "-baixo", 1) elif("-direita" in plan): plan = plan.replace("-direita", "-esquerda", 1) elif ("-esquerda" in plan): plan = plan.replace("-esquerda", "-direita", 1) elif("-frente" in plan): plan = plan.replace("-frente", "-tras", 1) elif("-tras" in plan): plan = plan.replace("-tras", "-frente", 1) 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"] period = dict_period[js_movement["velocidade"]] + dict_calc[js_movement["raio"]] ray = dict_ray[js_movement["raio"]] x = dict_axis[plan][0] y = dict_axis[plan][1] #z = dict_axis[plan]][2] opposite_side = dict_axis[plan][3] reverse_way = dict_axis[plan][4] k = round(period / 2) if (opposite_side) else 0 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 if (is_semicircular): limit = round(period / 2) + k iterator = None if (reverse_way): iterator = reversed(range(k, limit + 1)) else: iterator = range(k, limit + 1) for i in iterator: 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 # 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