diff --git a/Makefile b/Makefile index 7fb27d2..93511e6 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,17 @@ -JSON = $(JSON_RETILINEO) +JSON = $(JSON_CIRCULAR) # ---------------------------- -# JSON = $(JSON_CIRCULAR) -# JSON = $(JSON_CONTATO_ALISAR) -# JSON = $(JSON_CONTATO_COCAR) -# JSON = $(JSON_CONTATO_TOCAR) -# JSON = $(JSON_CONTATO_RISCAR) -# JSON = $(JSON_FACIAL) -# JSON = $(JSON_HELICOIDAL) -# JSON = $(JSON_PONTUAL) -# JSON = $(JSON_RETILINEO) -# JSON = $(JSON_SEMI_CIRCULAR) -# JSON = $(JSON_SENOIDAL) +# JSON = $(JSON_CIRCULAR) [OK] +# JSON = $(JSON_CONTATO_ALISAR) [--] +# JSON = $(JSON_CONTATO_COCAR) [--] +# JSON = $(JSON_CONTATO_TOCAR) [--] +# JSON = $(JSON_CONTATO_RISCAR) [--] +# JSON = $(JSON_FACIAL) [OK] +# JSON = $(JSON_HELICOIDAL) [OK] +# JSON = $(JSON_PONTUAL) [OK] +# JSON = $(JSON_RETILINEO) [OK] +# JSON = $(JSON_SEMICIRCULAR) [OK] +# JSON = $(JSON_SENOIDAL) [OK] # ---------------------------- JSON_CIRCULAR = \ @@ -22,7 +22,8 @@ JSON_CIRCULAR = \ "movimentos": [ \ { \ "facial": {}, \ - "mao_esquerda": { \ + "mao_esquerda": {}, \ + "mao_direita": { \ "circular": { \ "plano": "esquerda-cima", \ "raio": "pequeno", \ @@ -30,11 +31,10 @@ JSON_CIRCULAR = \ "lado_oposto": false, \ "sentido_inverso": false, \ "articulacao": 80, \ - "configuracao": 10, \ - "orientacao": 20 \ + "configuracao": 15, \ + "orientacao": 18 \ } \ - }, \ - "mao_direita": {} \ + } \ } \ ] \ }' @@ -47,7 +47,8 @@ JSON_CONTATO_ALISAR = \ "movimentos": [ \ { \ "facial": {}, \ - "mao_direita": { \ + "mao_direita": {}, \ + "mao_esquerda": { \ "contato": { \ "movimento_orientacao": "paralelo", \ "alisar": { \ @@ -56,8 +57,7 @@ JSON_CONTATO_ALISAR = \ "orientacao": 11 \ } \ } \ - }, \ - "mao_esquerda": {} \ + } \ } \ ] \ }' @@ -70,7 +70,8 @@ JSON_CONTATO_COCAR = \ "movimentos": [ \ { \ "facial": {}, \ - "mao_direita": { \ + "mao_direita": {}, \ + "mao_esquerda": { \ "contato": { \ "cocar": { \ "articulacao": 71, \ @@ -78,8 +79,7 @@ JSON_CONTATO_COCAR = \ "orientacao": 11 \ } \ } \ - }, \ - "mao_esquerda": {} \ + } \ } \ ] \ }' @@ -92,7 +92,8 @@ JSON_CONTATO_TOCAR = \ "movimentos": [ \ { \ "facial": {}, \ - "mao_direita": { \ + "mao_direita": {}, \ + "mao_esquerda": {}, \ "contato": { \ "tocar": { \ "articulacao": 71, \ @@ -100,8 +101,7 @@ JSON_CONTATO_TOCAR = \ "orientacao": 11 \ } \ } \ - }, \ - "mao_esquerda": {} \ + } \ } \ ] \ }' @@ -114,7 +114,8 @@ JSON_CONTATO_RISCAR = \ "movimentos": [ \ { \ "facial": {}, \ - "mao_direita": { \ + "mao_direita": {}, \ + "mao_esquerda": { \ "contato": { \ "riscar": { \ "articulacao": 71, \ @@ -122,8 +123,7 @@ JSON_CONTATO_RISCAR = \ "orientacao": 11 \ } \ } \ - }, \ - "mao_esquerda": {} \ + } \ } \ ] \ }' @@ -135,22 +135,28 @@ JSON_FACIAL = \ "interpolacao": "normal", \ "movimentos": [ \ { \ + "mao_direita": {}, \ + "mao_esquerda": {}, \ "facial": { \ "expressao": 10, \ "transicao": "normal", \ "duracao": "normal" \ - }, \ + } \ + }, \ + { \ "mao_direita": {}, \ - "mao_esquerda": {} \ + "mao_esquerda": {}, \ + "facial": { \ + } \ }, \ { \ + "mao_direita": {}, \ + "mao_esquerda": {}, \ "facial": { \ "expressao": 11, \ "transicao": "normal", \ "duracao": "normal" \ } \ - "mao_direita": {}, \ - "mao_esquerda": {} \ } \ ] \ }' @@ -163,20 +169,21 @@ JSON_HELICOIDAL = \ "movimentos": [ \ { \ "facial": {}, \ - "mao_esquerda": { \ + "mao_esquerda": {}, \ + "mao_direita": { \ "helicoidal": { \ "plano": "esquerda-cima", \ "raio": "pequeno", \ "velocidade": "normal", \ "lado_oposto": false, \ - "sentido_inverso": false, \ - "articulacao": 80, \ - "configuracao": 10, \ - "orientacao": 20 \ + "sentido_inverso": true, \ + "articulacao": 79, \ + "configuracao": 0, \ + "orientacao": 64 \ } \ - }, \ - "mao_direita": {} \ + } \ } \ + ] \ }' JSON_PONTUAL = \ @@ -187,14 +194,13 @@ JSON_PONTUAL = \ "movimentos": [ \ { \ "facial": {}, \ - "mao_direita": { \ + "mao_direita": {}, \ + "mao_esquerda": { \ "pontual": { \ "articulacao": 71, \ "configuracao": 19, \ "orientacao": 11 \ } \ - }, \ - "mao_esquerda": { \ } \ } \ ] \ @@ -208,41 +214,42 @@ JSON_RETILINEO = \ "movimentos": [ \ { \ "facial": {}, \ - "mao_direita": { \ + "mao_direita": {}, \ + "mao_esquerda": { \ "retilineo": { \ "articulacao_inicial": 71, \ - "articulacao_final": 75, \ - "configuracao": 19, \ - "orientacao": 11 \ + "configuracao_inicial": 19, \ + "orientacao_inicial": 11, \ + "articulacao_final": 78, \ + "configuracao_final": 19, \ + "orientacao_final": 11 \ } \ - }, \ - "mao_esquerda": { \ } \ } \ ] \ }' -JSON_SEMI_CIRCULAR = \ +JSON_SEMICIRCULAR = \ '{ \ "userId": "lavid", \ - "sinal": "modelo_semi_circular", \ + "sinal": "modelo_semicircular", \ "interpolacao": "normal", \ "movimentos": [ \ { \ "facial": {}, \ - "mao_esquerda": { \ - "circular": { \ + "mao_esquerda": {}, \ + "mao_direita": { \ + "semicircular": { \ "plano": "esquerda-cima", \ "raio": "pequeno", \ "velocidade": "normal", \ "lado_oposto": false, \ "sentido_inverso": false, \ "articulacao": 80, \ - "configuracao": 10, \ - "orientacao": 20 \ + "configuracao": 15, \ + "orientacao": 18 \ } \ - }, \ - "mao_direita": {} \ + } \ } \ ] \ }' @@ -254,26 +261,22 @@ JSON_SENOIDAL = \ "interpolacao": "normal", \ "movimentos": [ \ { \ - "facial": { \ - "expressao": 10, \ - "transicao": "normal", \ - "duracao": "normal" \ - }, \ - "mao_esquerda": { \ + "facial": {}, \ + "mao_esquerda": {}, \ + "mao_direita": { \ "circular": { \ "plano": "esquerda-cima", \ "raio": "pequeno", \ "velocidade": "normal", \ "lado_oposto": false, \ "sentido_inverso": false, \ - "articulacao": 80, \ - "configuracao": 10, \ - "orientacao": 20 \ + "articulacao": 79, \ + "configuracao": 0, \ + "orientacao": 64 \ } \ - }, \ - "mao_direita": { \ } \ } \ + ] \ }' BLEND = avatar_cartoon_v2.74.blend diff --git a/controller.py b/controller.py index 0a2c935..63ef9f4 100644 --- a/controller.py +++ b/controller.py @@ -18,6 +18,6 @@ try: # result = subprocess.call(['blender', '-b', blend_path, '-P', main_path, '--', sys.argv[1]], stdout = open('bpy.log', 'w')) result = subprocess.call(['blender', '-b', blend_path, '-P', main_path, '--', sys.argv[1]]) except: - result = pyutil.print_stack_trace(__file__) + result = pyutil.print_stack_trace() exit(result) diff --git a/decode.py b/decode.py index 080deb3..3c39fb9 100644 --- a/decode.py +++ b/decode.py @@ -2,81 +2,33 @@ import bpy import moves import util -def circular_semicircular(js_movement, current_frame, frame_jump, is_right_hand, is_semicircular): - dict_ray = { - 'pequeno': 0.5, - 'normal': 1.0, - 'grande': 1.5 - } - dict_period = { - 'lento': 55, - 'normal': 45, - 'rapido': 35 - } - # decodificar valores - ray = dict_ray[js_movement['raio']] - period = dict_period[js_movement['velocidade']] - # diminuir a velocidade - if (js_movement['velocidade'] == 'lento'): - period += 10 - # aumentar a velocidade - elif (js_movement['velocidade'] == 'rapido'): - period -= 10 - # definir eixos do movimento - if (js_movement['plano'] == 'frente-esquerda'): - x, y = 2, 0 - elif (js_movement['plano'] == 'frente-cima'): - x, y = 2, 1 - else: - x, y = 0, 1 - # mao usada (direita/esquerda) - if (is_right_hand): - ik = bpy.context.object.pose.bones['ik_FK.R'] - else: - ik = bpy.context.object.pose.bones['ik_FK.L'] - #current_frame = insert_keyframe_pose_default(current_frame, [ik], ['location']) - current_frame = moves.circular(ik, current_frame, ray, period, x, y, js_movement['lado_oposto'], js_movement['sentido_inverso'], is_semicircular) - return current_frame +def facial(js_facial, current_frame, frame_jump): + return moves.facial(js_facial, current_frame, frame_jump) def contato(js_movement, current_frame, frame_jump, is_right_hand): sub_type = next(iter(js_movement.keys())) mov_param = js_movement[sub_type] action = 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 - current_frame = current_frame + 2*frame_jump + current_frame = current_frame + (2 * frame_jump) return moves.contato(action, sub_type, mov_param, bones, is_right_hand, current_frame, frame_jump) -def helicoidal(js_movement, current_frame, frame_jump, is_right_hand): - return moves.helicoidal(js_movement, current_frame, frame_jump, is_right_hand) - -def pontual(js_movement, current_frame, frame_jump, is_right_hand): - return moves.pontual(js_movement, current_frame, frame_jump, is_right_hand) - -def retilineo(js_movement, current_frame, frame_jump, is_right_hand): - return moves.retilineo(js_movement, current_frame, frame_jump, is_right_hand) - -def semicircular(js_movement, current_frame, frame_jump, is_right_hand, is_semicircular): - return moves.semi_circular(js_movement, current_frame, frame_jump, is_right_hand) - -def senoidal(js_movement, current_frame, frame_jump, is_right_hand): - return moves.senoidal(js_movement, current_frame, frame_jump, is_right_hand) - def hand_mov(current_frame, frame_jump, js_mao, is_right_hand): if (js_mao == {}): - return current_frame + return current_frame + (2 * frame_jump) movement_name = next(iter(js_mao.keys())) - if (movement_name == 'circular'): - current_frame = circular_semicircular(js_mao[movement_name], current_frame, frame_jump, is_right_hand, False) - elif (movement_name == 'semicircular'): - current_frame = circular_semicircular(js_mao[movement_name], current_frame, frame_jump, is_right_hand, True) - elif (movement_name == 'contato'): + if (movement_name == "circular"): + current_frame = moves.circular(js_mao[movement_name], current_frame, frame_jump, is_right_hand) + elif (movement_name == "semicircular"): + current_frame = moves.semicircular(js_mao[movement_name], current_frame, frame_jump, is_right_hand) + elif (movement_name == "contato"): current_frame = contato(js_mao[movement_name], current_frame, frame_jump, is_right_hand) - elif (movement_name == 'helicoidal'): - current_frame = espiral(js_mao[movement_name], current_frame, frame_jump, is_right_hand) - elif (movement_name == 'pontual'): - current_frame = pontual(js_mao[movement_name], current_frame, frame_jump, is_right_hand) - elif (movement_name == 'retilineo'): - current_frame = retilineo(js_mao[movement_name], current_frame, frame_jump, is_right_hand) - elif (movement_name == 'senoidal'): - current_frame = senoidal(js_mao[movement_name], current_frame, frame_jump, is_right_hand) + elif (movement_name == "helicoidal"): + current_frame = moves.helicoidal(js_mao[movement_name], current_frame, frame_jump, is_right_hand) + elif (movement_name == "pontual"): + current_frame = moves.pontual(js_mao[movement_name], current_frame, frame_jump, is_right_hand) + elif (movement_name == "retilineo"): + current_frame = moves.retilineo(js_mao[movement_name], current_frame, frame_jump, is_right_hand) + elif (movement_name == "senoidal"): + current_frame = moves.senoidal(js_mao[movement_name], current_frame, frame_jump, is_right_hand) return current_frame + frame_jump diff --git a/facial.py b/facial.py deleted file mode 100644 index 1962673..0000000 --- a/facial.py +++ /dev/null @@ -1,113 +0,0 @@ -# -*- coding: UTF-8 -*- - -import bpy -import util - -# duracao na posicao selecionada -dict_duration = { - 'inicial': 10, - 'lento': 15, - 'normal': 10, - 'rapido': 5, - 'final': 10, -} - -# tempo de entrada e saida na posicao selecionada -dict_transition = { - 'inicial': 0, - '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 = dict_transition['inicial']): - 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_transition[js_facial['transicao']] - # insere o primeiro keyframe - if (timeline_facial == 0): - timeline_facial = set_expression(timeline_facial, 0, initial_interpolation) - timeline_facial = set_expression(timeline_facial, index, frame_duration, frame_transition) - timeline_facial = set_expression(timeline_facial, 0, frame_duration) - return timeline_facial - -""" -# unit test -def main(): - timeline_facial = 0 - util.delete_all_keyframes() - expressoes = list(range(0, round(bpy.data.actions[util.facial_expression_id].frame_range[1]) + 1)) - expressoes = [10, 11] - for i in expressoes: - js_facial = { - "expressao": i, - "transicao": "normal", - "duracao": "normal" - } - timeline_facial = decode_expression(timeline_facial, js_facial, dict_duration['inicial']) - bpy.context.scene.frame_end = timeline_facial + dict_duration['final'] - bpy.ops.screen.animation_play(reverse = False) - -if __name__ == "__main__": - main() -""" \ No newline at end of file diff --git a/libras.py b/libras.py index fa8d6a7..1e0f755 100644 --- a/libras.py +++ b/libras.py @@ -4,6 +4,7 @@ import bpy # importa modulos do Python +import io import json import sys import os @@ -18,25 +19,15 @@ sys.path.insert(0, getcwd) import util import moves import pyutil -import facial import decode -# intervalos de interpolacao dos keyframes -dict_interpolation = { - 'inicial': 20, - 'lento': 15, - 'normal': 10, - 'rapido': 5, - 'final': 20 -} - -def insert_keyframe_pose_default(current_frame = 0, pose_bones = bpy.context.object.pose.bones, types_keyframe = ['location', 'rotation_quaternion']): +def insert_keyframe_pose_default(current_frame = 0, pose_bones = bpy.context.object.pose.bones, types_keyframe = ["location", "rotation_quaternion"]): for obj in (pose_bones): obj.bone.select = True for type_keyframe in types_keyframe: util.keyframe_insert(obj, type_keyframe, current_frame, False) obj.bone.select = False - return current_frame + return def pose_default(current_frame = 0, frame_jump = 0, actions = bpy.data.actions): for action in actions: @@ -54,55 +45,55 @@ def main(): try: js_input = json.loads(sys.argv[6]) - js_movimentos = js_input['movimentos'] - frame_jump = dict_interpolation[js_input['interpolacao']] + js_movimentos = js_input["movimentos"] + frame_jump = util.dict_interpolation[js_input["interpolacao"]] endFrame = pose_default(0, frame_jump) + timeline_facial = 0 timeline_mao_esquerda = 0 timeline_mao_direita = 0 - timeline_facial = 0 - # setar pose padrao inicial em todos os bones ('location' e 'rotation_quaternion') - endFrame += pose_default(dict_interpolation['inicial']) + # setar pose padrao inicial em todos os bones ("location" e "rotation_quaternion") + endFrame += pose_default(util.dict_interpolation["inicial"]) for i in range(0, len(js_movimentos)): + timeline_facial = endFrame timeline_mao_esquerda = endFrame timeline_mao_direita = endFrame # tenta decodificar objetos JSON try: - js_facial = js_movimentos[i]['facial'] + js_facial = js_movimentos[i]["facial"] except: js_facial = {} try: - js_mao_esquerda = js_movimentos[i]['mao_esquerda'] + js_mao_esquerda = js_movimentos[i]["mao_esquerda"] except: js_mao_esquerda = {} try: - js_mao_direita = js_movimentos[i]['mao_direita'] + js_mao_direita = js_movimentos[i]["mao_direita"] except: js_mao_direita = {} # faz tratamento dos objetos if (js_facial == {}): - print("movimento [%d] Exp facial = " % (i)) - timeline_facial = facial.set_expression(timeline_facial, 0) + pyutil.log("movimento [%d] Exp facial = " % (i)) else: - print("movimento [%d] Exp facial = [%d]" % (i, js_facial["expressao"])) - timeline_facial = facial.decode_expression(timeline_facial, js_facial) + pyutil.log("movimento [%d] Exp facial = [%d]" % (i, js_facial["expressao"])) + timeline_facial = decode.facial(js_facial, timeline_facial, frame_jump) if (js_mao_esquerda == {}): - print("movimento [%d] Mao Esquerda = " % (i)) + pyutil.log("movimento [%d] Mao Esquerda = " % (i)) # TODO posicionar mao esquerda na lateral do corpo else: - print("movimento [%d] Mao Esquerda = [%s]" % (i, next(iter(js_mao_esquerda.keys())))) + pyutil.log("movimento [%d] Mao Esquerda = [%s]" % (i, next(iter(js_mao_esquerda.keys())))) timeline_mao_esquerda = decode.hand_mov(timeline_mao_esquerda, frame_jump, js_mao_esquerda, False) if (js_mao_direita == {}): - print("movimento [%d] Mao Direita = " % (i)) + pyutil.log("movimento [%d] Mao Direita = " % (i)) # TODO posicionar mao direita na lateral do corpo else: - print("movimento [%d] Mao Direita = [%s]" % (i, next(iter(js_mao_direita.keys())))) + pyutil.log("movimento [%d] Mao Direita = [%s]" % (i, next(iter(js_mao_direita.keys())))) timeline_mao_direita = decode.hand_mov(timeline_mao_direita, frame_jump, js_mao_direita, True) endFrame = max(timeline_facial, timeline_mao_esquerda, timeline_mao_direita) @@ -110,12 +101,23 @@ def main(): # setar pose padrao final em todos os bones (location e rotation) endFrame = pose_default(endFrame, frame_jump) - endFrame += dict_interpolation['final'] + endFrame += util.dict_interpolation["final"] + + sinal = str(js_input["sinal"]) + user_id = str(js_input["userId"]) + directory = os.path.join(getcwd, "users", user_id) + + # exporta .blend + util.export_blend(directory, sinal + ".blend", 0, 0, endFrame) + + # exporta .json + util.export_json(js_input, directory, sinal + ".json") - util.render_sign(js_input["userId"], js_input["sinal"], endFrame) + # exporta .mp4 + util.render_sign(user_id, sinal, endFrame) except: - pyutil.print_stack_trace(__file__) + pyutil.print_stack_trace() raise if __name__ == "__main__": diff --git a/moves.py b/moves.py index 57c43a6..3946024 100644 --- a/moves.py +++ b/moves.py @@ -5,6 +5,51 @@ 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 @@ -26,13 +71,11 @@ def riscar(action, mov_param, bones, is_right_hand, initialFrame = 25, frameJump 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] @@ -51,7 +94,6 @@ def tocar(action, mov_param, bones, is_right_hand, initialFrame = 25, degree = 3 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 @@ -66,7 +108,6 @@ 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 @@ -81,7 +122,6 @@ def alisar(action, mov_param, bones, is_right_hand, initialFrame = 18, frameJump 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"): @@ -138,70 +178,192 @@ def alisar_diagonal(boneIK, to_right, repetition, initialFrame = 18, frameJump = # 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) +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 + } + ray = dict_ray[js_movement["raio"]] + period = dict_period[js_movement["velocidade"]] + opposite_side = js_movement["lado_oposto"] + reverse_way = js_movement["sentido_inverso"] + actions = util.right_hand_actions if (is_right_hand) else util.left_hand_actions + hand_param = read_hand_param(js_movement) + bones = util.right_bones_conf if (is_right_hand) else util.left_bones_conf + ik = bpy.context.object.pose.bones["ik_FK.R" if (is_right_hand) else "ik_FK.L"] + if (js_movement["velocidade"] == "lento"): + period += 10 + elif (js_movement["velocidade"] == "rapido"): + period -= 10 + if (js_movement["plano"] == "frente-esquerda"): + x, y = 2, 0 + elif (js_movement["plano"] == "frente-cima"): + x, y = 2, 1 + else: + x, y = 0, 1 + k = round(period / 2) if (opposite_side) else 0 + x %= 3 + y %= 3 + 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 - 1 + if (is_semicircular): + limit = round(period / 2) + 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) + util.keyframe_insert(ik, "rotation_quaternion", current_frame, False) + current_frame += 1 + return current_frame + +def helicoidal(js_movement, current_frame, frame_jump, is_right_hand): + dict_ray = { + "pequeno": 0.5, + "normal": 1.0, + "grande": 1.5 + } + dict_period = { + "lento": 55, + "normal": 45, + "rapido": 35 + } + ray = dict_ray[js_movement["raio"]] + period = dict_period[js_movement["velocidade"]] + opposite_side = js_movement["lado_oposto"] + reverse_way = js_movement["sentido_inverso"] + actions = util.right_hand_actions if (is_right_hand) else util.left_hand_actions + hand_param = read_hand_param(js_movement) + bones = util.right_bones_conf if (is_right_hand) else util.left_bones_conf + ik = bpy.context.object.pose.bones["ik_FK.R" if (is_right_hand) else "ik_FK.L"] + if (js_movement["velocidade"] == "lento"): + period += 10 + elif (js_movement["velocidade"] == "rapido"): + period -= 10 + if (js_movement["plano"] == "frente-esquerda"): + x, y, z = 2, 0, 1 + elif (js_movement["plano"] == "frente-cima"): + x, y, z = 2, 1, 0 else: - k = 0 - # evita estouro dos indices + x, y, z = 0, 1, 2 + k = round(period / 2) if (opposite_side) else 0 x %= 3 y %= 3 - # inverte direcao do movimento - if (usar_sentido_oposto): + if (reverse_way): 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) + 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 - 1 + 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))) + ik.location[z] = ik_loc[z] + (i / period) - ray + util.keyframe_insert(ik, "location", current_frame) + util.keyframe_insert(ik, "rotation_quaternion", current_frame, False) current_frame += 1 - util.keyframe_insert(obj, 'location', current_frame) - return periodo - 1 + return current_frame 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) + 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) + 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']] + 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) + 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']] + 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) + 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_ray = { + "pequeno": 0.5, + "normal": 1.0, + "grande": 1.5 + } + dict_period = { + "lento": 55, + "normal": 45, + "rapido": 35 + } + ray = dict_ray[js_movement["raio"]] + period = dict_period[js_movement["velocidade"]] + opposite_side = js_movement["lado_oposto"] + reverse_way = js_movement["sentido_inverso"] + actions = util.right_hand_actions if (is_right_hand) else util.left_hand_actions + hand_param = read_hand_param(js_movement) + bones = util.right_bones_conf if (is_right_hand) else util.left_bones_conf + ik = bpy.context.object.pose.bones["ik_FK.R" if (is_right_hand) else "ik_FK.L"] + if (js_movement["velocidade"] == "lento"): + period += 10 + elif (js_movement["velocidade"] == "rapido"): + period -= 10 + if (js_movement["plano"] == "frente-esquerda"): + x, y, z = 2, 0, 1 + elif (js_movement["plano"] == "frente-cima"): + x, y, z = 2, 1, 0 + else: + x, y, z = 0, 1, 2 + k = round(period / 2) if (opposite_side) else 0 + x %= 3 + y %= 3 + 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 - 1 + 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))) + #ik.location[z] = ik_loc[z] + (i / period) - ray + util.keyframe_insert(ik, "location", current_frame) + util.keyframe_insert(ik, "rotation_quaternion", current_frame, False) + current_frame += 1 return current_frame \ No newline at end of file diff --git a/pyutil.py b/pyutil.py index 732de01..489ddb3 100644 --- a/pyutil.py +++ b/pyutil.py @@ -1,140 +1,132 @@ # -*- coding: UTF-8 -*- -# @def Função para obter data e hora atual do sistema -# @param string Formato de data e hora -# @return string Retorna data e hora do sistema no momento da chamada -def getTimeStamp(dtFrmt='%Y-%m-%d_%H.%M.%S.%f'): - from datetime import datetime - if (dtFrmt == '%Y-%m-%d_%H.%M.%S.%f'): - # [:-3] Remove 3 casas decimais dos milisegundos (ms) - return datetime.now().strftime(dtFrmt)[:-3] +import datetime +import logging +import os +import shutil +import sys + +# @def funcao para obter data e hora atual do sistema +# @param string formato de data e hora +# @return string retorna data e hora do sistema no momento da chamada +def getTimeStamp(date_fmt = "%Y-%m-%d %H:%M:%S.%f"): + if ("%f" in date_fmt): + # [:-3] remove 3 casas decimais dos milisegundos (ms) + return datetime.datetime.now().strftime(date_fmt)[:-3] else: - return datetime.now().strftime(dtFrmt) - -# @def Função para gravar log dos eventos em arquivo -# @param string Mensagem a ser salva -# @param int indice do tipo de log 1: Debug, 2: Info, 3: Warn, 4: Error, 5: Critical -# @param String Caminho completo do arquivo de logs -# @param String Formato de tempo utilizado -def log(logMsg="", logLevel=2, logFile="events.log", dtFrmt='%Y-%m-%d %H:%M:%S'): - import logging - - logLevelArray = ["", "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL" ] - logLevel %= len(logLevelArray) - print("[%s] log %s: %s" % (getTimeStamp(), logLevelArray[logLevel], logMsg)) - - #logFormat='[%(asctime)s.%(msecs).03d] %(levelname)s: : %(message)s' - logFormat='[%(asctime)s.%(msecs).03d] %(levelname)s: %(message)s' - - if (logLevel == 1): - logging.basicConfig(filename=logFile, datefmt=dtFrmt, format=logFormat, level=logging.DEBUG) - logging.Formatter(fmt='%(asctime)s',datefmt='%Y/%m/%d,%H:%M:%S.%f') - logging.debug(logMsg) - - elif (logLevel == 2): - logging.basicConfig(filename=logFile, datefmt=dtFrmt, format=logFormat, level=logging.INFO) - logging.Formatter(fmt='%(asctime)s',datefmt='%Y/%m/%d,%H:%M:%S.%f') - logging.info(logMsg) - - elif (logLevel == 3): - logging.basicConfig(filename=logFile, datefmt=dtFrmt, format=logFormat, level=logging.WARN) - logging.Formatter(fmt='%(asctime)s',datefmt='%Y/%m/%d,%H:%M:%S.%f') - logging.warn(logMsg) - - elif (logLevel == 4): - logging.basicConfig(filename=logFile, datefmt=dtFrmt, format=logFormat, level=logging.ERROR) - logging.Formatter(fmt='%(asctime)s',datefmt='%Y/%m/%d,%H:%M:%S.%f') - logging.error(logMsg) - - elif (logLevel == 5): - logging.basicConfig(filename=logFile, datefmt=dtFrmt, format=logFormat, level=logging.CRITICAL) - logging.Formatter(fmt='%(asctime)s',datefmt='%Y/%m/%d,%H:%M:%S.%f') - logging.critical(logMsg) - -def test_log(): - msg = " This is a message " - log(msg + "Debug", 1) - log(msg + "Info", 2) - log(msg + "Warn", 3) - log(msg + "Error", 4) - log(msg + "Critical", 5) - -# test_log() - -# @def Função para exibir exceção -# @param string deve ser passado: "__file__" para identificar em qual arquivo ocorreu a exceção -# @return int Retorna 1 -def print_stack_trace(fromFile): - from sys import exc_info - from os.path import basename + return datetime.datetime.now().strftime(date_fmt) + +# @def funcao para gravar log dos eventos em arquivo +# @param string mensagem a ser salva +# @param int indice do tipo de log 0: apenas print, 1: debug, 2: info, 3: warn, 4: error, 5: critical +# @param string caminho completo do arquivo de logs +# @param string formato de tempo utilizado +# @return none +def log(msg = "", log_level = 2, log_file = "events.log"): + dict_level = { + 0: ["Print", None, None], + 1: ["DEBUG", logging.DEBUG, logging.debug], + 2: ["INFO", logging.INFO, logging.info], + 3: ["WARNING", logging.WARN, logging.warn], + 4: ["ERROR", logging.ERROR, logging.error], + 5: ["CRITICAL", logging.CRITICAL, logging.critical] + } + # log_format = "[%(asctime)s.%(msecs).03d] %(levelname)s: : %(message)s" + log_format = "[%(asctime)s.%(msecs).03d] %(levelname)s: %(message)s" + date_fmt = "%Y-%m-%d %H:%M:%S" + logging.basicConfig(filename = log_file, datefmt = date_fmt, format = log_format, level = dict_level[log_level][1]) + logging.Formatter(fmt = "%(asctime)s", datefmt = date_fmt) + log_level %= len(dict_level) + write_mode = dict_level[log_level][2] + print("[%s] %s: %s" % (getTimeStamp(), dict_level[log_level][0], msg)) + if (write_mode != None): + write_mode(msg) + return + +# @def funcao para exibir excecao +# @param string deve ser passado: "__file__" para identificar em qual modulo ocorreu a excecao +# @return int retorna 1 +def print_stack_trace(): error = "\n File name: %s\n Function name: %s\n Line code: %s\n Type exception: %s\n Message: %s" % ( - basename(fromFile), # basename(exc_info()[2].tb_frame.f_code.co_filename), - exc_info()[2].tb_frame.f_code.co_name, - exc_info()[2].tb_lineno, - exc_info()[0].__name__, - exc_info()[1] + os.path.basename(sys.exc_info()[2].tb_frame.f_code.co_filename), + sys.exc_info()[2].tb_frame.f_code.co_name, + sys.exc_info()[2].tb_lineno, + sys.exc_info()[0].__name__, + sys.exc_info()[1] ) log(error, 4) return 1 -# @def Função que verifica se um arquivo existe -# @param string filePath: Caminho do arquivo a ser checado -# @return bool Verdadeiro se o arquivo existir, Falso caso contrário -def file_exists(filePath): - from os.path import isfile, exists - if ((isfile(filePath) == 1) and (exists(filePath) == 1)): +# @def funcao que verifica se um arquivo existe +# @param string caminho do arquivo a ser checado +# @return bool verdadeiro se o arquivo existir, falso caso contrario +def file_exists(file_path): + if ((os.path.isfile(file_path) == 1) and (os.path.exists(file_path) == 1)): return True else: return False -# @def Função para renomear arquivo de video gerado pelo blender -# @see entrada: /temp/arquivo_video_0001-0250.mp4 -# @see saida: /temp/arquivo_video.mp4 -# @param string fileFullPath: Caminho do arquivo a ser renomeado -# @param bool useTimeStamp: Renomeia o arquivo de acordo com a data e hora do sistema -# @param bool overwrite: Sobreescreve o arquivo -# @return string Retorna o nome do arquivo renomeado -def file_rename(fileFullPath, useTimeStamp = False, overwrite = True): - from shutil import move - from os.path import abspath, basename, dirname, join, splitext - if (file_exists(fileFullPath) == False): +# @def funcao para renomear arquivo de video gerado pelo blender +# entrada: /temp/arquivo_video_0001-0250.mp4 +# saida: /temp/arquivo_video.mp4 +# @param string caminho do arquivo a ser renomeado +# @param bool renomeia o arquivo de acordo com a data e hora do sistema +# @param bool sobreescreve o arquivo +# @return string retorna o nome do arquivo renomeado +def file_rename(file_full_path, use_time_stamp = False, overwrite = True): + if (file_exists(file_full_path) == False): return "" - filePath = dirname(abspath(fileFullPath)) - filename = basename(splitext(fileFullPath)[0]) - extension = splitext(fileFullPath)[1] - filenameInv = "" - isValidChar = False - - # Percorre o "filename" do final para o inicio copiando caracteres após o primeiro '_' encontrado + file_path = os.path.dirname(os.path.abspath(file_full_path)) + filename = os.path.basename(os.path.splitext(file_full_path)[0]) + extension = os.path.splitext(file_full_path)[1] + filename_reversed = "" + valid_char = False + # percorre o "filename" do final para o inicio copiando caracteres apos o primeiro "_" encontrado for char in reversed(filename): - if (isValidChar == True): - filenameInv += char - if (char == '_'): - isValidChar = True + if (valid_char == True): + filename_reversed += char + if (char == "_"): + valid_char = True try: - - # Inverte sequencia de caracteres que foi copiada - filenameInv = filenameInv[::-1] - - if (useTimeStamp == True): - # Recupera novo fullPath + nome do arquivo + data/hora + extensão - newFilename = join(filePath, "%s_%s%s" % (filenameInv, getTimeStamp(), extension)) + # inverte sequencia de caracteres que foi copiada + filename_reversed = filename_reversed[::-1] + if (use_time_stamp == True): + # recupera novo file_full_path + nome do arquivo + data/hora + extensao + new_filename = os.path.join(file_path, "%s_%s%s" % (filename_reversed, getTimeStamp(), extension)) else: - # Recupera novo fullPath + nome do arquivo + extensão - newFilename = join(filePath, "%s%s" % (filenameInv, extension)) - - # Enumera o nome do arquivo caso o parametro "overwrite" seja "False" e o arquivo já exista + # recupera novo file_full_path + nome do arquivo + extensao + new_filename = os.path.join(file_path, "%s%s" % (filename_reversed, extension)) + # Enumera o nome do arquivo caso o parametro "overwrite" seja "False" e o arquivo ja exista if (overwrite == False): count = 0 - while (file_exists(newFilename) == True): + while (file_exists(new_filename) == True): count += 1 - # newFilename = join(filePath, "%s_%i%s" % (filenameInv, count, extension)) - newFilename = join(filePath, "%s_%0.4i%s" % (filenameInv, count, extension)) - - log("Rename: '%s' to: '%s'" %(fileFullPath, newFilename)) - move(fileFullPath, newFilename) - return newFilename - - except Exception as e: - printStackTrace(__file__) + # new_filename = join(file_path, "%s_%i%s" % (filename_reversed, count, extension)) + new_filename = os.path.join(file_path, "%s_%0.4i%s" % (filename_reversed, count, extension)) + # log('rename: "%s" to: "%s"' %(file_full_path, new_filename)) + shutil.move(file_full_path, new_filename) + return new_filename + except Exception: + print_stack_trace() return "" + +""" +# unit test +def main(): + msg = "This is a message of " + log(msg + "Print", 0) + log(msg + "Debug", 1) + log(msg + "Info", 2) + log(msg + "Warn", 3) + log(msg + "Error", 4) + log(msg + "Critical", 5) + filename = "sample_001-250.mp4" + video = open(filename, "w") + video.write + video.close + file_rename(filename) + return + +if __name__ == "__main__": + main() +""" \ No newline at end of file diff --git a/util.py b/util.py index 919cb68..d5261ed 100644 --- a/util.py +++ b/util.py @@ -1,11 +1,12 @@ # -*- coding: UTF-8 -*- import bpy +import copy +import json import math import os -import sys -import copy import pyutil +import sys from bmesh_collision import bmesh_check_intersect_objects armature = bpy.context.scene.objects.get('Armature.001') @@ -20,15 +21,13 @@ dict_bones = { "07_facial": ['BnPescoco', 'BnCabeca', 'BnSobrancCentro.L', 'BnSobrancCentro.R', 'BnSobrancLateral.L', 'BnSobrancLateral.R', 'BnPalpebSuper.L', 'BnPalpebInfe.L', 'BnSobrancCentro', 'BnLabioCentroSuper', 'BnBochecha.L', 'BnBochecha.R', 'BnLabioCentroInfer', 'BnBocaCanto.L', 'BnBocaCanto.R', 'BnMandibula', 'BnLingua', 'BnLingua.003', 'BnLingua.001', 'BnLingua.002', 'BnPalpebSuper.R', 'BnPalpebInfe.R', 'BnOlhosMira', 'BnOlhoMira.L', 'BnOlhoMira.R', 'BnOlho.L', 'BnOlho.R'] } -right_bones_conf = dict_bones["01_conf_direita"] + dict_bones["03_pa_direita"] + dict_bones["05_orient_direita"] - -left_bones_conf = dict_bones["02_conf_esquerda"] + dict_bones["04_pa_esquerda"] + dict_bones["06_orient_esquerda"] - -# Vetor com indices de cada bone do lado direito -#rightBonesConf = [1, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66] - -# Vetor com indices de cada bone do lado esquerdo -#leftBonesConf = [0, 43, 44, 45, 46, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82] +dict_interpolation = { + "inicial": 20, + "lento": 15, + "normal": 10, + "rapido": 5, + "final": 20 +} # Movimento coçar - Índices de poses cocar_mao_aberta_index = 55 @@ -36,21 +35,29 @@ cocar_mao_fechada_index = 24 cocar_orientation_index = 11 # Action expressão facial -facial_expression_id = '07_facial' +facial_expression_id = "07_facial" facial_expression_action = [facial_expression_id] # Actions mão direita -conf_direita_id = '01_conf_direita' -pa_direita_id = '03_pa_direita' -orient_direita_id = '05_orient_direita' +conf_direita_id = "01_conf_direita" +pa_direita_id = "03_pa_direita" +orient_direita_id = "05_orient_direita" right_hand_actions = [conf_direita_id, pa_direita_id, orient_direita_id] # Actions mão esquerda -conf_esquerda_id = '02_conf_esquerda' -pa_esquerda_id = '04_pa_esquerda' -orient_esquerda_id = '06_orient_esquerda' +conf_esquerda_id = "02_conf_esquerda" +pa_esquerda_id = "04_pa_esquerda" +orient_esquerda_id = "06_orient_esquerda" left_hand_actions = [conf_esquerda_id, pa_esquerda_id, orient_esquerda_id] +all_actions = [conf_direita_id, conf_esquerda_id, pa_direita_id, pa_esquerda_id, orient_direita_id, orient_esquerda_id, facial_expression_id] + +all_bones = dict_bones[conf_direita_id] + dict_bones[conf_esquerda_id] + dict_bones[pa_direita_id] + dict_bones[pa_esquerda_id] + dict_bones[orient_direita_id] + dict_bones[orient_esquerda_id] + dict_bones[facial_expression_id] + +right_bones_conf = dict_bones[conf_direita_id] + dict_bones[pa_direita_id] + dict_bones[orient_direita_id] + +left_bones_conf = dict_bones[conf_esquerda_id] + dict_bones[pa_esquerda_id] + dict_bones[orient_esquerda_id] + last_keyframe_dict = {} def select_bones(bones = bpy.context.object.pose.bones): @@ -86,7 +93,6 @@ def delete_all_keyframes(): obj.animation_data_clear() return -# Função responsável por selecionar as pose-libs e setar os frames def setPose(actions, parametesConf, positionFrames, bones, collisionFlag = True): for x in range(len(positionFrames)): for l in range(len(actions)): @@ -110,7 +116,7 @@ def internal_keyframe_insert(bone, path, positionFrame, collisionFlag = True, ro if ("ik_FK" in bone.name and bone.location.z < 1): bone.location.z = 1 bone.bone.select = True - bone.keyframe_insert(data_path = path, index = -1, frame = positionFrame) + bone.keyframe_insert(data_path = path, index = -1, group = bone.name, frame = positionFrame) bone.bone.select = False keyframe_id = bone.name + "_" + path last_keyframe = last_keyframe_dict[keyframe_id] if keyframe_id in last_keyframe_dict else 0 @@ -184,7 +190,6 @@ def check_collision(objName, otherObjName, initFrame, endFrame): scene = bpy.context.scene startFrame = initFrame + int(math.fabs((endFrame - initFrame)/2)) collisionFrame = -1 - for i in range(startFrame, endFrame + 1, 1): scene.frame_set(i) obj = scene.objects.get(objName) @@ -222,10 +227,9 @@ def configure_output(): bpy.context.scene.render.tile_y = 240 return -def render_sign(user_id, nome_sinal = "sinal", frame_final = bpy.context.scene.frame_end): +def render_sign(user_id = "", sinal = "", frame_final = bpy.context.scene.frame_end): getcwd = os.path.dirname(os.path.abspath(__file__)) - bpy.context.scene.render.filepath = getcwd + "/users/" + str(user_id) + "/"+ nome_sinal + "_" - bpy.ops.wm.save_as_mainfile(filepath=getcwd + "/users/" + str(user_id) + "/"+ nome_sinal + ".blend") + bpy.context.scene.render.filepath = os.path.join(getcwd, "users", user_id, sinal + "_") bpy.context.scene.frame_end = frame_final pyutil.log("Gerando Video... Frames: %i" % (frame_final)) bpy.ops.render.render(animation = True, write_still = False, layer = "", scene = "") @@ -233,6 +237,39 @@ def render_sign(user_id, nome_sinal = "sinal", frame_final = bpy.context.scene.f bpy.ops.wm.quit_blender() return +def make_dir(directory): + if not os.path.exists(directory): + os.makedirs(directory) + return True + return False + +def export_blend(directory, filename, frame_start, frame_current, frame_end): + tmp_frame_start = bpy.context.scene.frame_start + tmp_frame_current = bpy.context.scene.frame_current + tmp_frame_end = bpy.context.scene.frame_end + bpy.context.scene.frame_start = frame_start + bpy.context.scene.frame_current = frame_current + bpy.context.scene.frame_end = frame_end + make_dir(directory) + bpy.ops.wm.save_as_mainfile(filepath = os.path.join(directory, filename)) + bpy.context.scene.frame_start = tmp_frame_start + bpy.context.scene.frame_current = tmp_frame_current + bpy.context.scene.frame_end = tmp_frame_end + +def export_json(obj, directory, filename, inline = True): + make_dir(directory) + fp = open(os.path.join(directory, filename), 'w', encoding = "utf-8") + fp.write( + json.dumps( + obj, + ensure_ascii = False, + indent = None if (inline) else 4, + separators = (",", ":") if (inline) else None + ) + ) + fp.close + return + def validate_rotation(bone, endFrame, startFrame = 0): if (endFrame - startFrame == 1): return True -- libgit2 0.21.2