123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645 |
- '''
- CSV importer for the BCK animation type
- CSVs that come from the j3d animation editor program
- animations for now will be imported with linear interpolation
- seems to me that the majority of the animations just use linear
- as the interpolation method between keyframes of animation rows
- '''
- import bpy, math, re
- from mathutils import Matrix
- from .my_functions import *
- def read_csv_bck(context, filepath, import_type):
-
- scene = bpy.context.scene
-
-
- if (scene.objects.active == None
- or
- scene.objects.active.type != 'ARMATURE'):
- error_string = "No Armature object selected. Select one and try again."
- print("\n### ERROR ###\n" + error_string + "\n### ERROR ###\n")
- show_message(error_string, "Error exporting collada file", 'ERROR')
- return {'FINISHED'}
-
-
- armature = scene.objects.active
- print()
- print("###############")
- print("Armature found: %s" % armature.name)
- print()
-
-
- bpy.ops.object.select_all(action='DESELECT')
- scene.objects.active = None
-
-
- armature.select = True
- scene.objects.active = armature
-
-
- f = open(filepath, 'r', encoding='utf-8')
-
-
-
-
-
-
-
- line = f.readline()
-
- if not (line.find("bck") + 1):
- error_string = "CSV is not for the BCK animation type. Check the file and try again."
- print("\n### ERROR ###\n" + error_string + "\n### ERROR ###\n")
- show_message(error_string, "Error importing CSV file data", 'ERROR')
- return {'FINISHED'}
-
-
-
- bone_count = 0
- while True:
-
- line = f.readline()
-
-
- if (line.find("Scale X") + 1):
- bone_count = bone_count + 1
-
-
-
- if (line == "" or line == '\n'):
- break
-
-
- if (bone_count != len(armature.data.bones)):
- error_string = "Number of bones on the Armature is different than the number of animated bones on the CSV. Check the CSV file and try again."
- print("\n### ERROR ###\n" + error_string + "\n### ERROR ###\n")
- show_message(error_string, "Error importing CSV file data", 'ERROR')
- return {'FINISHED'}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- if (import_type == True):
-
-
-
-
- f = open(filepath, 'r', encoding='utf-8')
-
- line = f.readline()
-
-
- csv_first_line = line.split(',')
- animation_length = int(csv_first_line[1])
-
-
- bpy.data.scenes["Scene"].frame_end = int(csv_first_line[1])
-
-
- line = f.readline()
-
-
- csv_keyframe_numbers = re.findall('[0-9]+', line)
- csv_keyframe_numbers = [int(string) for string in csv_keyframe_numbers]
-
-
-
-
-
- for bone_number in range(bone_count):
-
-
- pose_bone = armature.pose.bones[bone_number]
- print("Reading/Writing animation for bone: %s" % (pose_bone.name))
-
-
- pose_bone.rotation_mode = 'XYZ'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- bone_anim_data = [[], [], [], [], [], [], [], [], []]
-
-
-
-
- for i in range(9):
-
- line = f.readline()
- row_data = line.split(',')
-
-
-
- while (len(row_data) != (len(csv_keyframe_numbers) + 3)):
- row_data.append("")
-
-
-
-
- for j in range(len(row_data)):
-
-
-
- if (j < 3):
- continue
-
-
-
-
- if (row_data[j] == "" or row_data[j] == '\n'):
- bone_anim_data[i].append(None)
- else:
- bone_anim_data[i].append(float(row_data[j]))
-
-
-
-
-
-
-
-
- for k in range(len(csv_keyframe_numbers)):
-
-
- scene.frame_set(csv_keyframe_numbers[k])
-
-
- if (bone_anim_data[0][k] != None):
- pose_bone.scale[0] = bone_anim_data[0][k]
- pose_bone.keyframe_insert(data_path = 'scale', index = 0)
- if (bone_anim_data[1][k] != None):
- pose_bone.scale[1] = bone_anim_data[1][k]
- pose_bone.keyframe_insert(data_path = 'scale', index = 1)
- if (bone_anim_data[2][k] != None):
- pose_bone.scale[2] = bone_anim_data[2][k]
- pose_bone.keyframe_insert(data_path = 'scale', index = 2)
-
-
- if (bone_anim_data[3][k] != None):
- pose_bone.rotation_euler[0] = math.radians(bone_anim_data[3][k])
- pose_bone.keyframe_insert(data_path = 'rotation_euler', index = 0)
- if (bone_anim_data[4][k] != None):
- pose_bone.rotation_euler[1] = math.radians(bone_anim_data[4][k])
- pose_bone.keyframe_insert(data_path = 'rotation_euler', index = 1)
- if (bone_anim_data[5][k] != None):
- pose_bone.rotation_euler[2] = math.radians(bone_anim_data[5][k])
- pose_bone.keyframe_insert(data_path = 'rotation_euler', index = 2)
-
-
- if (bone_anim_data[6][k] != None):
- pose_bone.location[0] = bone_anim_data[6][k] / 100
- pose_bone.keyframe_insert(data_path = 'location', index = 0)
- if (bone_anim_data[7][k] != None):
- pose_bone.location[1] = bone_anim_data[7][k] / 100
- pose_bone.keyframe_insert(data_path = 'location', index = 1)
- if (bone_anim_data[8][k] != None):
- pose_bone.location[2] = bone_anim_data[8][k] / 100
- pose_bone.keyframe_insert(data_path = 'location', index = 2)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- else:
-
-
-
-
- f = open(filepath, 'r', encoding='utf-8')
-
- line = f.readline()
-
-
- csv_first_line = line.split(',')
- animation_length = int(csv_first_line[1])
-
-
- bpy.data.scenes["Scene"].frame_end = int(csv_first_line[1])
-
-
- line = f.readline()
-
-
- csv_keyframe_numbers = re.findall('[0-9]+', line)
- csv_keyframe_numbers = [int(string) for string in csv_keyframe_numbers]
-
-
-
-
-
- for bone_number in range(bone_count):
-
-
- pose_bone = armature.pose.bones[bone_number]
- data_bone = armature.data.bones[bone_number]
- print("Reading/Writing animation for bone: %s" % (pose_bone.name))
-
-
- pose_bone.rotation_mode = 'XYZ'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- bone_anim_data = [[], [], [], [], [], [], [], [], []]
-
-
-
-
- for i in range(9):
-
- line = f.readline()
- row_data = line.split(',')
-
-
-
- while (len(row_data) != (len(csv_keyframe_numbers) + 3)):
- row_data.append("")
-
-
-
-
-
-
-
-
-
- j = 0
- for k in range(animation_length + 1):
-
-
-
-
-
-
- if (k != csv_keyframe_numbers[j]):
- bone_anim_data[i].append(None)
- continue
-
-
-
-
-
-
-
- if (row_data[j + 3] == "" or row_data[j + 3] == '\n'):
- bone_anim_data[i].append(None)
- else:
- bone_anim_data[i].append(float(row_data[j + 3]))
-
-
- j = j + 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- convert_rot_anim_to_180(bone_anim_data[3], csv_keyframe_numbers)
- convert_rot_anim_to_180(bone_anim_data[4], csv_keyframe_numbers)
- convert_rot_anim_to_180(bone_anim_data[5], csv_keyframe_numbers)
-
-
-
-
-
-
-
-
-
- for k in range(len(csv_keyframe_numbers)):
-
-
- kf_num = csv_keyframe_numbers[k]
-
- scene.frame_set(kf_num)
-
-
-
-
-
-
-
-
-
-
-
- anim_temp = []
-
-
-
-
-
-
-
- if (bone_anim_data[0][kf_num] != None):
- anim_temp.append(bone_anim_data[0][kf_num])
- else:
-
- a = find_left_right(bone_anim_data[0], kf_num)
-
- anim_temp.append(interpolate(a[0], a[1], a[2], a[3], kf_num, None, "linear"))
-
-
-
- if (bone_anim_data[1][kf_num] != None):
- anim_temp.append(bone_anim_data[1][kf_num])
- else:
-
- a = find_left_right(bone_anim_data[1], kf_num)
-
- anim_temp.append(interpolate(a[0], a[1], a[2], a[3], kf_num, None, "linear"))
-
-
-
- if (bone_anim_data[2][kf_num] != None):
- anim_temp.append(bone_anim_data[2][kf_num])
- else:
-
- a = find_left_right(bone_anim_data[2], kf_num)
-
- anim_temp.append(interpolate(a[0], a[1], a[2], a[3], kf_num, None, "linear"))
-
-
-
-
-
-
-
- if (bone_anim_data[3][kf_num] != None):
- anim_temp.append(math.radians(bone_anim_data[3][kf_num]))
- else:
-
- a = find_left_right(bone_anim_data[3], kf_num)
-
- anim_temp.append(math.radians(interpolate(a[0], a[1], a[2], a[3], kf_num, None, "linear")))
-
-
-
- if (bone_anim_data[4][kf_num] != None):
- anim_temp.append(math.radians(bone_anim_data[4][kf_num]))
- else:
-
- a = find_left_right(bone_anim_data[4], kf_num)
-
- anim_temp.append(math.radians(interpolate(a[0], a[1], a[2], a[3], kf_num, None, "linear")))
-
-
-
- if (bone_anim_data[5][kf_num] != None):
- anim_temp.append(math.radians(bone_anim_data[5][kf_num]))
- else:
-
- a = find_left_right(bone_anim_data[5], kf_num)
-
- anim_temp.append(math.radians(interpolate(a[0], a[1], a[2], a[3], kf_num, None, "linear")))
-
-
-
-
-
-
-
-
- if (bone_anim_data[6][kf_num] != None):
- anim_temp.append(bone_anim_data[6][kf_num] / 100)
- else:
-
- a = find_left_right(bone_anim_data[6], kf_num)
-
- anim_temp.append(interpolate(a[0], a[1], a[2], a[3], kf_num, None, "linear") / 100)
-
-
-
- if (bone_anim_data[7][kf_num] != None):
- anim_temp.append(bone_anim_data[7][kf_num] / 100)
- else:
-
- a = find_left_right(bone_anim_data[7], kf_num)
-
- anim_temp.append(interpolate(a[0], a[1], a[2], a[3], kf_num, None, "linear") / 100)
-
-
-
- if (bone_anim_data[8][kf_num] != None):
- anim_temp.append(bone_anim_data[8][kf_num] / 100)
- else:
-
- a = find_left_right(bone_anim_data[8], kf_num)
-
- anim_temp.append(interpolate(a[0], a[1], a[2], a[3], kf_num, None, "linear") / 100)
-
-
-
-
-
-
- anim_irp_mat = calc_translation_matrix(anim_temp[6], anim_temp[7], anim_temp[8]) * calc_rotation_matrix(anim_temp[3], anim_temp[4], anim_temp[5]) * calc_scale_matrix(anim_temp[0], anim_temp[1], anim_temp[2])
-
-
-
-
-
-
-
- if (bone_number == 0):
- anim_rp_mat = anim_irp_mat
- else:
- anim_rp_mat = (data_bone.parent.matrix_local.inverted() * data_bone.matrix_local).inverted() * anim_irp_mat
-
-
-
-
-
-
- bone_scale = anim_rp_mat.to_scale()
-
- bone_rotation = anim_rp_mat.to_euler('XYZ')
-
- bone_translation = anim_rp_mat.to_translation()
-
-
-
-
-
-
-
-
-
-
-
-
-
- if (bone_anim_data[0][kf_num] != None
- or
- bone_anim_data[1][kf_num] != None
- or
- bone_anim_data[2][kf_num] != None):
- pose_bone.scale[0] = bone_scale[0]
- pose_bone.keyframe_insert(data_path = 'scale', index = 0)
- pose_bone.scale[1] = bone_scale[1]
- pose_bone.keyframe_insert(data_path = 'scale', index = 1)
- pose_bone.scale[2] = bone_scale[2]
- pose_bone.keyframe_insert(data_path = 'scale', index = 2)
-
-
-
- if (bone_anim_data[3][kf_num] != None
- or
- bone_anim_data[4][kf_num] != None
- or
- bone_anim_data[5][kf_num] != None):
- pose_bone.rotation_euler[0] = bone_rotation[0]
- pose_bone.keyframe_insert(data_path = 'rotation_euler', index = 0)
- pose_bone.rotation_euler[1] = bone_rotation[1]
- pose_bone.keyframe_insert(data_path = 'rotation_euler', index = 1)
- pose_bone.rotation_euler[2] = bone_rotation[2]
- pose_bone.keyframe_insert(data_path = 'rotation_euler', index = 2)
-
-
-
- if (bone_anim_data[6][kf_num] != None
- or
- bone_anim_data[7][kf_num] != None
- or
- bone_anim_data[8][kf_num] != None):
- pose_bone.location[0] = bone_translation[0]
- pose_bone.keyframe_insert(data_path = 'location', index = 0)
- pose_bone.location[1] = bone_translation[1]
- pose_bone.keyframe_insert(data_path = 'location', index = 1)
- pose_bone.location[2] = bone_translation[2]
- pose_bone.keyframe_insert(data_path = 'location', index = 2)
-
-
-
-
-
-
-
-
- curves = bpy.context.active_object.animation_data.action.fcurves
- for curve in curves:
- for keyframe in curve.keyframe_points:
- keyframe.interpolation = 'LINEAR'
-
-
- return {'FINISHED'}
- from bpy_extras.io_utils import ExportHelper
- from bpy.props import StringProperty, BoolProperty, EnumProperty
- from bpy.types import Operator
- class Import_CSV_BCK(Operator, ExportHelper):
- """Import a CSV file from J3D Animation Editor of the BCK animation type. Armature to which the animation must be applied must be the only armature in scene and must be the correct one for the animation"""
- bl_idname = "import_scene.csv_bck"
- bl_label = "Import CSV of BCK (from J3D Anim Editor)"
- filename_ext = ".csv"
- filter_glob = StringProperty(
- default="*.csv",
- options={'HIDDEN'},
- maxlen=255,
- )
-
- import_type = BoolProperty( name = "Ignore Rest Pose",
- description = "Ignore all bone's rest poses and apply animations as SMG does. Modifies the bone's original rest pose.",
- default = False,
- )
-
- def execute(self, context):
- return read_csv_bck(context, self.filepath, self.import_type)
- def menu_import_csv_bck(self, context):
- self.layout.operator(Import_CSV_BCK.bl_idname, text="CSV of BCK (from J3D Animation Editor) (.csv)")
- bpy.utils.register_class(Import_CSV_BCK)
- bpy.types.INFO_MT_file_import.append(menu_import_csv_bck)
- bpy.ops.import_scene.csv_bck('INVOKE_DEFAULT')
|